/// <summary> /// Pushes the version taken as a parameter /// Will return any changes that conflicts /// IMPORTANT: The version is not commited at the server before null is returned! /// </summary> /// <param name="path">The path to the repository to push</param> /// <param name="number">The version number used to identify the right version</param> /// <param name="log">The changes given by a number of text-.</param> /// <param name="user">The user to submit changes.</param> /// <returns> /// Any changes that conflicts or null if version is commited /// </returns> /// <exception cref="System.ArgumentNullException">Log can't be null</exception> /// <exception cref="System.ArgumentException">Log can't be empty</exception> public string[][] PushVersion(String path, int number, string[] log, User user) { if (log == null) throw new ArgumentNullException("Log can't be null"); if (log.Length < 1) throw new ArgumentException("Log can't be empty"); if (user == null) throw new ArgumentNullException("User can't be null"); if (String.IsNullOrEmpty(user.Name)) throw new ArgumentException("User's name is invalid: " + user.Name); if (String.IsNullOrEmpty(user.Password)) throw new ArgumentException("User's password is invalid"); if (user.MAC == null) throw new ArgumentNullException("User's MAC address is invalid (" + user.MAC + " and can therefore not push"); Console.WriteLine("[" + DateTime.Now + "]: " + "User is pushing to the server: " + user.MAC); //See if the user is known - if not: Throw an exception //Connect(user); var returnArray = new string[0][]; // Test that the version number is correct - otherwise we'll just store things at the wrong places. var vcs = new ServerVersionControlSystem(path, _fileSystem); var currentVersion = vcs.GetLatestVersionNumber(); if (currentVersion != number - 1) { throw new ArgumentException("Can not push version " + number + " to the server version " + currentVersion); } // If the last user that attempted to push is the same as the current user, no conflicts will occur. if (PushedLastVersion(user)) { // We can assume that everything has been resolved client side and execute all the changes made IList<AbstractChange> changeList = ChangeParser.ParseChanges(log).Where(item => item != null).ToList(); // Store the version SaveChanges(number, user, vcs, changeList); } else { String[] simpleChanges = SearchForSimpleChanges(log); String[,] complexChanges = SearchForComplexChanges(log); ISet<String> conflictingPathsOnServerSet = new SortedSet<string>(); ISet<String> conflictingPathsOnClientSet = new SortedSet<string>(); //Get paths to all text files in project directory and all sub directories. String absolutePath = vcs.GetFileSystemRoot() + path; IList<String> projectFilesList = new List<string>(Directory.GetFileSystemEntries(absolutePath, "*", SearchOption.AllDirectories).Where(s => s.Contains(FileSystem.META_DIR) == false)); // Discover potential conflicts for (int i = 0; i < projectFilesList.Count; i++) { projectFilesList[i] = projectFilesList[i].Substring(vcs.GetFileSystemRoot().Length); } foreach (String filePath in simpleChanges) { if (projectFilesList.Contains(filePath)) { conflictingPathsOnServerSet.Add(filePath); conflictingPathsOnClientSet.Add(filePath); } } for (int i = 0; i < complexChanges.Length; i++) { if (projectFilesList.Contains(complexChanges[i, 0])) { conflictingPathsOnServerSet.Add(complexChanges[i, 0]); conflictingPathsOnClientSet.Add(complexChanges[i, 1]); } } // If no conflicts arises we can save the change to the file system if (conflictingPathsOnServerSet.Count == 0) { SaveChanges(number, user, vcs, ChangeParser.ParseChanges(log)); } else // Otherwise we find the conflicting paths and return the contents of the file on the // server for the client to merge { IList<String> conflictingPathsOnServer = new List<string>(conflictingPathsOnServerSet); IList<String> conflictingPathsOnClient = new List<string>(conflictingPathsOnClientSet); var list = new List<string[]>(); for (int i = 0; i < conflictingPathsOnServer.Count; i++) { var fileList = new List<string>() { conflictingPathsOnClient[i] }; fileList.AddRange(vcs.ReadAllLines(conflictingPathsOnServer[i])); list.Add(fileList.ToArray()); } returnArray = list.ToArray(); } } // Save the last MAC adress _lastPushUser = user.Name; //AddToPushHistory(user); // Return the conflicts to the client return returnArray; }
/// <summary> /// Get the logs containing changes for the specified versions /// </summary> /// <param name="path">The relative path to the project root</param> /// <param name="from">The version number from</param> /// <param name="to">The version number to</param> /// <returns></returns> public String[][] GetVersions(String path, int from, int to) { var vcs = new ServerVersionControlSystem(path, _fileSystem); IEnumerable<int> enu = Enumerable.Range(from, to - from + 1); IEnumerable<String[]> esu = enu.Select(vcs.GetVersionLog); return new List<string[]>(esu).ToArray(); }