private void SetSubmoduleData(VsrModule currentModule, SubmoduleInfoResult result, string noBranchText, IVsrModule topProject) { var submodules = topProject.GetSubmodulesLocalPaths().OrderBy(submoduleName => submoduleName).ToArray(); if (submodules.Any()) { string localPath = result.Module.WorkingDir.Substring(topProject.WorkingDir.Length); localPath = Path.GetDirectoryName(localPath).ToPosixPath(); foreach (var submodule in submodules) { string path = topProject.GetSubmoduleFullPath(submodule); string name = submodule + GetBranchNameSuffix(path, noBranchText); bool bold = false; if (submodule == localPath) { result.CurrentSubmoduleName = currentModule.GetCurrentSubmoduleLocalPath(); bold = true; } var smi = new SubmoduleInfo { Text = name, Path = path, Bold = bold }; result.SuperSubmodules.Add(smi); } } }
/// <summary> /// Delete index.lock in the current working folder. /// </summary> /// <param name="includeSubmodules"> /// If <see langword="true"/> all submodules will be scanned for index.lock files and have them delete, if found. /// </param> /// <exception cref="FileDeleteException">Unable to delete specific index.lock.</exception> public void UnlockIndex(bool includeSubmodules = true) { var workingFolderIndexLock = Path.Combine(_gitDirectoryResolver.Resolve(_module.WorkingDir), IndexLock); if (!includeSubmodules) { DeleteIndexLock(workingFolderIndexLock); return; } // get the list of files to delete var submodules = _module.GetSubmodulesLocalPaths(); var list = submodules.Select(sm => { var submodulePath = _module.GetSubmoduleFullPath(sm); var submoduleIndexLock = Path.Combine(_gitDirectoryResolver.Resolve(submodulePath), IndexLock); return(submoduleIndexLock); }).Union(new[] { workingFolderIndexLock }); foreach (var indexLock in list) { DeleteIndexLock(indexLock); } }
public void UnlockIndex_should_delete_submodule_locks_if_requested() { _file.Exists(_indexLockFile).Returns(true); var submoduleGitHubWorkingDir = $@"{_workingDir}\Externals\Git.hub\"; var submoduleNbugWorkingDir = $@"{_workingDir}\Externals\NBug\"; var submoduleGitHubWorkingDirGitDir = $@"{_gitWorkingDir}\modules\Externals\Git.hub\"; var submoduleNBugWorkingDirGitDir = $@"{_gitWorkingDir}\modules\Externals\NBug\"; var submoduleGitHubIndexLock = $@"{_gitWorkingDir}\modules\Externals\Git.hub\{IndexLock}"; var submoduleNBugIndexLock = $@"{_gitWorkingDir}\modules\Externals\NBug\{IndexLock}"; _module.GetSubmodulesLocalPaths().Returns(new[] { "Externals/Git.hub", "Externals/NBug" }); _module.GetSubmoduleFullPath(Arg.Any <string>()) .Returns(submoduleGitHubWorkingDir, submoduleNbugWorkingDir); _gitDirectoryResolver.Resolve(submoduleGitHubWorkingDir).Returns(submoduleGitHubWorkingDirGitDir); _gitDirectoryResolver.Resolve(submoduleNbugWorkingDir).Returns(submoduleNBugWorkingDirGitDir); _file.Exists(submoduleGitHubIndexLock).Returns(true); _file.Exists(submoduleNBugIndexLock).Returns(false); _manager.UnlockIndex(true); _file.Received().Delete(submoduleGitHubIndexLock); _file.DidNotReceive().Delete(submoduleNBugIndexLock); }
/// <summary> /// Parse git-status --porcelain=1 and git-diff --name-status /// Outputs are similar, except that git-status has status for both worktree and index /// </summary> /// <param name="module">The VsrModule</param> /// <param name="statusString">Output from Git command</param> /// <param name="fromDiff">Parse git-diff</param> /// <param name="staged">The staged status <see cref="GitItemStatus"/>, only relevant for git-diff (parsed for git-status)</param> /// <returns>list with the git items</returns> private static IReadOnlyList <GitItemStatus> GetAllChangedFilesFromString_v1(IVsrModule module, string statusString, bool fromDiff, StagedStatus staged) { var diffFiles = new List <GitItemStatus>(); if (string.IsNullOrEmpty(statusString)) { return(diffFiles); } string trimmedStatus = RemoveWarnings(statusString); // Doesn't work with removed submodules var submodules = module.GetSubmodulesLocalPaths(); // Split all files on '\0' (WE NEED ALL COMMANDS TO BE RUN WITH -z! THIS IS ALSO IMPORTANT FOR ENCODING ISSUES!) var files = trimmedStatus.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries); for (int n = 0; n < files.Length; n++) { if (string.IsNullOrEmpty(files[n])) { continue; } int splitIndex; if (fromDiff) { splitIndex = -1; } else { // Note that this fails for files with spaces (git-status --porcelain=1 is deprecated) var splitChars = new[] { '\t', ' ' }; splitIndex = files[n].IndexOfAny(splitChars, 1); } string status; string fileName; if (splitIndex < 0) { if (n >= files.Length - 1) { // Illegal, ignore continue; } status = files[n]; fileName = files[n + 1]; n++; } else { status = files[n].Substring(0, splitIndex); fileName = files[n].Substring(splitIndex); } char x = status[0]; char y = status.Length > 1 ? status[1] : ' '; if (fromDiff && staged == StagedStatus.WorkTree && x == 'U') { // git-diff has two lines to inform that a file is modified and has a merge conflict continue; } if (x != '?' && x != '!' && x != ' ') { GitItemStatus gitItemStatusX; var stagedX = fromDiff ? staged : StagedStatus.Index; if (x == 'R' || x == 'C') { // Find renamed files... string nextFile = n + 1 < files.Length ? files[n + 1] : ""; gitItemStatusX = GitItemStatusFromCopyRename(stagedX, fromDiff, nextFile, fileName, x, status); n++; } else { gitItemStatusX = GitItemStatusFromStatusCharacter(stagedX, fileName, x); } if (submodules.Contains(gitItemStatusX.Name)) { gitItemStatusX.IsSubmodule = true; } diffFiles.Add(gitItemStatusX); } if (fromDiff || y == ' ') { continue; } GitItemStatus gitItemStatusY; var stagedY = StagedStatus.WorkTree; if (y == 'R' || y == 'C') { // Find renamed files... string nextFile = n + 1 < files.Length ? files[n + 1] : ""; gitItemStatusY = GitItemStatusFromCopyRename(stagedY, false, nextFile, fileName, y, status); n++; } else { gitItemStatusY = GitItemStatusFromStatusCharacter(stagedY, fileName, y); } if (submodules.Contains(gitItemStatusY.Name)) { gitItemStatusY.IsSubmodule = true; } diffFiles.Add(gitItemStatusY); } return(diffFiles); }