Beispiel #1
0
        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}");
        }
Beispiel #2
0
        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}'");
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
        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("");
        }