void PullCommand(string[] args) { #pragma warning restore 414 PullConflictStrategy conflictStrategy = PullConflictStrategy.Ask; if (args.Length > 0) { if (IsFlagParam(args[0], "l")) { conflictStrategy = PullConflictStrategy.KeepLocal; } else if (IsFlagParam(args[0], "r")) { conflictStrategy = PullConflictStrategy.OverWriteWithRemote; } else if (IsFlagParam(args[0], "a")) { throw BadParameter($"Unknown parameter '{args[0]}'"); } } var localRepository = GetExistingLocalRepository(); localRepository.Pull(conflictStrategy); UI.Print($"Your local repository is now up to date with {localRepository.FullRepositoryName}"); }
private void SwitchToBranch(string branchName, PullConflictStrategy conflictStrategy) { if (branchName.StartsWith("-")) { throw BadParameter($"Unknown parameter '{branchName}'"); } var repository = GetExistingLocalRepository(); repository.SwitchToBranch(branchName, conflictStrategy); UI.PrintLine($"Current local branch is now '{branchName}'"); }
public void SwitchToBranch(string branchName, PullConflictStrategy conflictStrategy) { string remoteCommitSha = null; bool branchIsCommitSha = false; if (branchName.LooksLikeSha1Hash()) { if (Api.GetCommitTreeSha(branchName) == null) { throw new InvalidOperationException("No commit exists with the specified SHA hash in the remote repsitory"); } else { remoteCommitSha = branchName; branchIsCommitSha = true; } } else { if (!BranchExistsRemotely(branchName)) { throw new InvalidOperationException($"Branch '{branchName}' doesn't exist remotely, you can create it with 'ngh -n {branchName}'"); } if (branchName.Equals(LocalBranchName, StringComparison.InvariantCultureIgnoreCase)) { throw new InvalidOperationException($"Branch '{branchName}' is already the current local branch, if you want to get the latest remote version do 'ngh pull'."); } remoteCommitSha = Api.GetBranchCommitSha(branchName); } var oldLocalBranchName = LocalBranchName; if (!branchIsCommitSha) { LocalBranchName = branchName; } if (remoteCommitSha == LocalCommitSha) { UI.PrintLine($"'{oldLocalBranchName}' is up to date with '{branchName}', nothing to pull"); } else { Pull(conflictStrategy, remoteCommitSha); } UpdateStateFile(); }
public void Pull(PullConflictStrategy conflictStrategy, string remoteCommitSha = null) { UI.PrintLine("Checking remote status..."); if (!ExistsRemotely()) { throw new InvalidOperationException("The remote repository doesn't exist!"); } if (remoteCommitSha == null) { if (!BranchExistsRemotely()) { throw new InvalidOperationException($"Branch '{LocalBranchName}' doesn't exist remotely!"); } remoteCommitSha = Api.GetBranchCommitSha(LocalBranchName); } if (remoteCommitSha == LocalCommitSha) { throw new InvalidOperationException("Your local repository is up to date with remote, nothing to pull"); } UI.PrintLine("Calculating changes..."); var newRemoteFileReferences = GetRemoteFileReferences(remoteCommitSha); var oldRemoteFileReferences = ParseTreeFile(); var remoteState = CalculateRemoteState(oldRemoteFileReferences, newRemoteFileReferences); var localState = GetLocalState(); var filenamesToDownload = remoteState.AddedFiles.Union(remoteState.ModifiedFiles).ToList(); var filenamesToDeleteLocally = remoteState.DeletedFiles.ToList(); //* Conflict type #1: file was modified both remotely and locally var filenamesModifiedRemotelyAndLocally = remoteState.ModifiedFiles.Intersect(localState.ModifiedFiles); foreach (var filename in filenamesModifiedRemotelyAndLocally) { UI.Print($"\r\n{filename} was modified both locally and remotely"); if (conflictStrategy == PullConflictStrategy.Ask) { UI.Print($".\r\nDo you want to keep the [L]ocal version or to overwrite it with the [R]emote version? "); ConsoleKey key = UI.ReadKey(ConsoleKey.L, ConsoleKey.R); UI.PrintLine(""); if (key == ConsoleKey.L) { filenamesToDownload.Remove(filename); } } else if (conflictStrategy == PullConflictStrategy.KeepLocal) { UI.PrintLine(", the local copy will be kept."); filenamesToDownload.Remove(filename); } else { UI.PrintLine(", the remote copy will be downloaded."); } } //* Conflict type #2: file was modified remotely but deleted locally var filenamesModifiedRemotelyButDeletedLocally = remoteState.ModifiedFiles.Intersect(localState.DeletedFiles); foreach (var filename in filenamesModifiedRemotelyButDeletedLocally) { UI.Print($"\r\n{filename} was modified remotely but deleted locally"); if (conflictStrategy == PullConflictStrategy.Ask) { UI.Print($".\r\nDo you want to keep the file [D]eleted or to download the [R]emote version? "); ConsoleKey key = UI.ReadKey(ConsoleKey.D, ConsoleKey.R); UI.PrintLine(""); if (key == ConsoleKey.D) { filenamesToDownload.Remove(filename); } } else if (conflictStrategy == PullConflictStrategy.KeepLocal) { UI.PrintLine(", the file will remain deleted."); filenamesToDownload.Remove(filename); } else { UI.PrintLine(", the remote copy will be downloaded."); } } //* Conflict type #3: file was deleted remotely but modified locally var filenamesDeletedRemotelyButModifiedLocally = remoteState.DeletedFiles.Intersect(localState.ModifiedFiles); foreach (var filename in filenamesDeletedRemotelyButModifiedLocally) { UI.Print($"\r\n{filename} was deleted remotely but modified locally"); if (conflictStrategy == PullConflictStrategy.Ask) { UI.Print($".\r\nDo you want to [D]elete the local file or [K]eep it? "); ConsoleKey key = UI.ReadKey(ConsoleKey.D, ConsoleKey.K); UI.PrintLine(""); if (key == ConsoleKey.K) { filenamesToDeleteLocally.Remove(filename); } } else if (conflictStrategy == PullConflictStrategy.KeepLocal) { filenamesToDeleteLocally.Remove(filename); UI.PrintLine(", the local copy will be kept."); } else { UI.PrintLine(", the local copy will be deleted."); } } //* Conflict type #4: file was added remotely and locally var filenamesAddedRemotelyAndLocally = remoteState.AddedFiles.Intersect(localState.AddedFiles); foreach (var filename in filenamesAddedRemotelyAndLocally) { UI.Print($"\r\n{filename} was added both locally and remotely"); if (conflictStrategy == PullConflictStrategy.Ask) { UI.Print($".\r\nDo you want to keep the [L]ocal file or to download the [R]emote version? "); ConsoleKey key = UI.ReadKey(ConsoleKey.L, ConsoleKey.R); UI.PrintLine(""); if (key == ConsoleKey.L) { filenamesToDownload.Remove(filename); } } else if (conflictStrategy == PullConflictStrategy.KeepLocal) { filenamesToDownload.Remove(filename); UI.PrintLine(", the local copy will be kept."); } else { UI.PrintLine(", the remote copy will be downloaded."); } } UI.PrintLine(""); var newRemoteFileReferencesByName = newRemoteFileReferences.ToDictionary(r => r.Path); foreach (var filename in filenamesToDownload) { UI.PrintLine($"Downloading {filename} ..."); var fileContents = Api.GetBlob(newRemoteFileReferencesByName[filename].BlobSha); Directory.CreateFile(fileContents, filename); Directory.SetUnmodified(filename); } foreach (var filename in filenamesToDeleteLocally) { UI.PrintLine($"Deleting {filename} ..."); Directory.DeleteFile(filename); } LocalCommitSha = remoteCommitSha; UpdateStateFile(); UpdateTreeFile(newRemoteFileReferences); UI.PrintLine(""); }