Esempio n. 1
0
        public async Task <R> UndoUncommittedFileAsync(string path, CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync(
                $"checkout --force -- \"{path}\"", CancellationToken.None);

            if (result.IsFaulted)
            {
                if (IsFileUnkwon(result, path))
                {
                    R deleteResult = DeleteFile(path, result);
                    if (deleteResult.IsFaulted)
                    {
                        return(R.Error($"Failed to delete {path}", deleteResult.Exception));
                    }

                    Log.Info($"Undid file {path}");
                    return(R.Ok);
                }

                return(R.Error($"Failed to undo file {path}", result.AsException()));
            }

            Log.Info($"Undid file {path}");
            return(R.Ok);
        }
Esempio n. 2
0
        public async Task <R <string> > GetFileDiffAsync(string sha, string path, CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync(
                $"diff --patch --root --find-renames --unified=100000  {sha}^..{sha} -- \"{path}\" ", ct);

            if (result.IsFaulted)
            {
                if (result.Error.StartsWith("fatal: ambiguous argument"))
                {
                    // Failed to get diff for sha, might be root commit, so try again
                    CmdResult2 showRootResult = await gitCmdService.RunCmdAsync(
                        $"show --patch --root {sha} -- \"{path}\"", ct);

                    if (showRootResult.IsOk)
                    {
                        Log.Info($"Got file diff patch for root {sha}");
                        return(R.From(showRootResult.Output));
                    }
                }

                return(R.Error($"Failed to get file diff for {sha}", result.AsException()));
            }

            Log.Info($"Got path for {sha}");
            return(R.From(result.Output));
        }
Esempio n. 3
0
        private async Task <R <IReadOnlyList <string> > > UndoAndCleanFolderAsync(
            string cleanArgs, CancellationToken ct)
        {
            R <CmdResult2> result = await gitCmdService.RunAsync("reset --hard", ct);

            if (result.IsFaulted)
            {
                return(R.Error("Reset failed.", result.Exception));
            }

            CmdResult2 cleanResult = await gitCmdService.RunCmdAsync($"clean {cleanArgs}", ct);

            if (cleanResult.IsFaulted)
            {
                if (IsFailedToRemoveSomeFiles(cleanResult, out IReadOnlyList <string> failedFiles))
                {
                    Log.Warn($"Failed to clean {failedFiles.Count} files");
                    return(R.From(failedFiles));
                }

                return(R.Error(cleanResult.AsException()));
            }

            return(R.From(EmptyFileList));
        }
Esempio n. 4
0
        public async Task <R> FetchRefsAsync(IEnumerable <string> refspecs, CancellationToken ct)
        {
            string refsText = string.Join(" ", refspecs);
            string args     = $"{FetchRefsArgs} {refsText}";

            Log.Debug($"Fetching {refsText} ...");

            void Progress(string text)
            {
                Log.Debug($"Progress: {text}");
            }

            CmdResult2 result = await gitCmdService.RunCmdWitProgressAsync(args, Progress, ct);

            if (result.IsFaulted)
            {
                if (IsNoRemote(result))
                {
                    return(R.Ok);
                }
                return(R.Error("Failed to fetch", result.AsException()));
            }

            return(R.Ok);
        }
        private async Task <CmdResult2> RunGitCmsAsync(
            string gitArgs, GitOptions options, string sessionId, CancellationToken ct)
        {
            AdjustOptions(options, sessionId);

            // Log.Debug($"Running: {GitCmdPath} {gitArgs}");
            CmdOptions cmdOptions = ToCmdOptions(options);
            string     gitCmdPath = GitCmdPath;
            CmdResult2 result     = await cmd.RunAsync(gitCmdPath, gitArgs, cmdOptions, ct);

            if (result.IsFaulted &&
                !result.IsCanceled &&
                !(result.ExitCode == 1 && string.IsNullOrEmpty(result.Error)))
            {
                Track.Event("Git-error", $"{result.ElapsedMs}ms: Exit {result.ExitCode}: {result.Command} {result.Arguments}\nError:\n{result.ErrorMessage}");
            }
            else
            {
                Track.Event("Git", $"{result.ElapsedMs}ms: {result.Command} {result.Arguments}");
                var replace = result.ToString().Replace($"\"{gitCmdPath}\"", "git");
                Log.Debug($"{result.ElapsedMs}ms: {replace}");
            }

            return(result);
        }
Esempio n. 6
0
        private static bool IsFailedToRemoveSomeFiles(CmdResult2 result, out IReadOnlyList <string> failedFiles)
        {
            // Check if error message contains any "warning: failed to remove <file>:"
            failedFiles = CleanOutputRegEx.Matches(result.Error).OfType <Match>()
                          .Select(match => match.Groups[1].Value).ToList();

            return(failedFiles.Any());
        }
        private string TryGetCmdVersion(string cmdPath)
        {
            CmdResult2 result = cmd.Run(cmdPath, "version");

            return(result.ExitCode == 0 && result.Output.StartsWithOic("git version ")
                                ? result.Output.Substring(12).Trim()
                                : null);
        }
        private R <CmdResult2> AsR(CmdResult2 result)
        {
            if (result.IsFaulted)
            {
                Error error = R.Error(result.AsException());
                return(error);
            }

            return(result);
        }
Esempio n. 9
0
        public async Task <R> RemoveAsync(string path, CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync($"rm \"{path}\"", ct);

            if (result.IsFaulted)
            {
                return(R.Error($"Failed remove {path}", result.AsException()));
            }

            return(R.Ok);
        }
Esempio n. 10
0
        public async Task <R <GitTag> > AddTagAsync(string sha, string tagName, CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync($"tag {tagName} {sha}", ct);

            if (result.IsFaulted)
            {
                return(R.Error($"Failed to add tag {tagName} at {sha}", result.AsException()));
            }

            Log.Info($"Added {tagName} at {sha}");
            return(new GitTag(sha, tagName));
        }
Esempio n. 11
0
        public async Task <R> RemoveNoteAsync(string sha, string notesRef, CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync(
                $"-c core.notesRef={notesRef} notes remove --ignore-missing {sha}", ct);

            if (result.IsFaulted)
            {
                return(R.Error("Failed to remove note", result.AsException()));
            }

            Log.Info($"Removed note");
            return(R.Ok);
        }
Esempio n. 12
0
        public async Task <R> PushAsync(CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync(PushArgs, ct);

            if (result.IsFaulted)
            {
                if (IsNoRemoteBranch(result))
                {
                    return(R.Ok);
                }
                return(R.Error("Failed to push", result.AsException()));
            }

            return(R.Ok);
        }
Esempio n. 13
0
        public async Task <R> AppendNoteAsync(
            string sha, string notesRef, string note, CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync(
                $"-c core.notesRef={notesRef} notes append --allow-empty -m\"{note}\" {sha}", ct);

            if (result.IsFaulted)
            {
                return(R.Error("Failed to add note", result.AsException()));
            }


            Log.Info($"Added note {note.Length} length");
            return(R.Ok);
        }
Esempio n. 14
0
        public async Task <R> PushDeleteRemoteBranchAsync(string branchName, CancellationToken ct)
        {
            Log.Debug($"Pushing delete branch {branchName} ...");
            CmdResult2 result = await gitCmdService.RunCmdAsync($"{PushArgs} --delete {branchName}", ct);

            if (result.IsFaulted)
            {
                if (IsNoRemote(result))
                {
                    return(R.Ok);
                }
                return(R.Error("Failed to push", result.AsException()));
            }

            return(R.Ok);
        }
Esempio n. 15
0
        private static bool GetMergeStatus(CmdResult2 result, out string mergeMessage)
        {
            bool isMergeInProgress = false;

            mergeMessage = null;
            string mergeIpPath  = Path.Combine(result.WorkingDirectory, ".git", "MERGE_HEAD");
            string mergeMsgPath = Path.Combine(result.WorkingDirectory, ".git", "MERGE_MSG");

            if (File.Exists(mergeIpPath))
            {
                isMergeInProgress = true;
                mergeMessage      = File.ReadAllText(mergeMsgPath).Trim();
            }

            return(isMergeInProgress);
        }
Esempio n. 16
0
        private IReadOnlyList <GitFile> ParseFiles(CmdResult2 result)
        {
            List <GitFile> files = new List <GitFile>();

            foreach (string line in result.OutputLines)
            {
                string filePath = line.Substring(2).Trim();

                GitFileStatus status = GitFileStatus.Modified;

                if (line.StartsWith("DD ") ||
                    line.StartsWith("AU ") ||
                    line.StartsWith("UA "))
                {
                    // How to do reproduce this ???
                    status = GitFileStatus.Conflict;
                }
                else if (line.StartsWith("UU "))
                {
                    status = GitFileStatus.Conflict | GitFileStatus.ConflictMM;
                }
                else if (line.StartsWith("AA "))
                {
                    status = GitFileStatus.Conflict | GitFileStatus.ConflictAA;
                }
                else if (line.StartsWith("UD "))
                {
                    status = GitFileStatus.Conflict | GitFileStatus.ConflictMD;
                }
                else if (line.StartsWith("DU "))
                {
                    status = GitFileStatus.Conflict | GitFileStatus.ConflictDM;
                }
                else if (line.StartsWith("?? ") || line.StartsWith(" A "))
                {
                    status = GitFileStatus.Added;
                }
                else if (line.StartsWith(" D ") || line.StartsWith("D"))
                {
                    status = GitFileStatus.Deleted;
                }

                files.Add(new GitFile(result.WorkingDirectory, filePath, null, status));
            }

            return(files);
        }
Esempio n. 17
0
        public async Task <R <IReadOnlyList <GitTag> > > GetAllTagsAsync(CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync("show-ref -d --tags", ct);

            if (result.IsFaulted)
            {
                if (!(result.ExitCode == 1 && string.IsNullOrEmpty(result.Output)))
                {
                    return(R.Error("Failed to list tags", result.AsException()));
                }
            }

            IReadOnlyList <GitTag> tags = ParseTags(result);

            Log.Info($"Got {tags.Count} tags");
            return(R.From(tags));
        }
Esempio n. 18
0
        public async Task <R <IReadOnlyList <string> > > GetRefsIdsAsync(CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync("show-ref", ct);

            if (result.IsFaulted)
            {
                if (result.ExitCode != 1)
                {
                    return(R.Error("Failed to get refs", result.AsException()));
                }
            }

            IReadOnlyList <string> refs = result.OutputLines.ToList();

            Log.Info($"Got {refs.Count} refs");
            return(R.From(refs));
        }
Esempio n. 19
0
        public async Task <R> PushTagAsync(string tagName, CancellationToken ct)
        {
            Log.Debug($"Pushing tag {tagName} ...");

            CmdResult2 result = await gitCmdService.RunCmdAsync($"{PushArgs} {tagName}", ct);

            if (result.IsFaulted)
            {
                if (IsNoRemote(result))
                {
                    return(R.Ok);
                }
                return(R.Error("Failed to push tag", result.AsException()));
            }

            return(R.Ok);
        }
Esempio n. 20
0
        private GitConflicts ParseConflicts(CmdResult2 result)
        {
            List <GitConflictFile> files = new List <GitConflictFile>();

            string filePath = null;
            string baseId   = null;
            string localId  = null;
            string remoteId = null;

            // Parsing lines, where there are 1,2 or 3 lines for one file before the next file lines
            foreach (string line in result.OutputLines)
            {
                string[] parts1 = line.Split("\t".ToCharArray());
                string[] parts2 = parts1[0].Split(" ".ToCharArray());
                string   path   = parts1[1].Trim();

                if (path != filePath && filePath != null)
                {
                    // Next file, store previous file
                    GitFileStatus status = GetConflictStatus(baseId, localId, remoteId);
                    if (status.HasFlag(GitFileStatus.Conflict))
                    {
                        files.Add(new GitConflictFile(result.WorkingDirectory, filePath, baseId, localId, remoteId, status));
                    }

                    baseId   = null;
                    localId  = null;
                    remoteId = null;
                }

                filePath = path;
                SetIds(parts2, ref baseId, ref localId, ref remoteId);
            }

            if (filePath != null)
            {
                // Add last file
                GitFileStatus status = GetConflictStatus(baseId, localId, remoteId);
                if (status.HasFlag(GitFileStatus.Conflict))
                {
                    files.Add(new GitConflictFile(result.WorkingDirectory, filePath, baseId, localId, remoteId, status));
                }
            }

            return(new GitConflicts(files));
        }
Esempio n. 21
0
        private static R DeleteFile(string path, CmdResult2 result)
        {
            try
            {
                string fullPath = Path.Combine(result.WorkingDirectory, path);
                if (File.Exists(fullPath))
                {
                    File.Delete(fullPath);
                    Log.Debug($"Deleted {fullPath}");
                }

                return(R.Ok);
            }
            catch (Exception e)
            {
                return(R.Error(e));
            }
        }
Esempio n. 22
0
        public async Task <R <bool> > TryCheckoutAsync(string name, CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync($"checkout --progress {name}", ct);

            if (result.IsFaulted)
            {
                if (IsUnknownName(result, name))
                {
                    Log.Info($"Unknown name: {name}");
                    return(false);
                }

                return(R.Error($"Failed to checkout {name}", result.AsException()));
            }

            Log.Info($"Checked out {name}");
            return(true);
        }
Esempio n. 23
0
        public async Task <R> PushBranchAsync(string branchName, CancellationToken ct)
        {
            Log.Debug($"Pushing branch {branchName} ...");
            string args = $"{PushArgs} -u refs/heads/{branchName}:refs/heads/{branchName}";

            CmdResult2 result = await gitCmdService.RunCmdAsync(args, ct);

            if (result.IsFaulted)
            {
                if (IsNoRemote(result))
                {
                    return(R.Ok);
                }
                return(R.Error("Failed to push", result.AsException()));
            }

            return(R.Ok);
        }
Esempio n. 24
0
        public async Task <R> PushRefsAsync(IEnumerable <string> refspecs, CancellationToken ct)
        {
            string refsText = string.Join(" ", refspecs);

            Log.Debug($"Pushing refs {refsText} ...");

            CmdResult2 result = await gitCmdService.RunCmdAsync($"{PushArgs} {refsText}", ct);

            if (result.IsFaulted)
            {
                if (IsNoRemote(result))
                {
                    return(R.Ok);
                }
                return(R.Error("Failed to push", result.AsException()));
            }

            return(R.Ok);
        }
Esempio n. 25
0
        private GitStatus ParseStatus(CmdResult2 result)
        {
            //if (result.Output.StartsWith("## No commits yet on"))
            //{
            //	return GitStatus2.Default;
            //}

            IReadOnlyList <GitFile> files = ParseFiles(result);

            int added      = files.Count(file => file.Status.HasFlag(GitFileStatus.Added));
            int deleted    = files.Count(file => file.Status.HasFlag(GitFileStatus.Deleted));
            int conflicted = files.Count(file => file.Status.HasFlag(GitFileStatus.Conflict));
            int modified   = files.Count - (added + deleted + conflicted);

            bool isMergeInProgress = GetMergeStatus(result, out string mergeMessage);

            return(new GitStatus(
                       modified, added, deleted, conflicted, isMergeInProgress, mergeMessage, files));
        }
Esempio n. 26
0
        public async Task <R> MergeAsync(string name, CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync(
                $"merge --no-ff --no-commit --stat --progress {name}", ct);

            if (result.IsFaulted)
            {
                if (result.ExitCode == 1 && IsConflicts(result))
                {
                    Log.Info($"Merge of {name} resulted in conflict(s)");
                    return(R.Ok);
                }

                return(R.Error($"Failed to merge branch {name}", result.AsException()));
            }

            Log.Info($"Merge of {name} was OK");
            return(R.Ok);
        }
Esempio n. 27
0
        public async Task <R <bool> > TryMergeFastForwardAsync(string name, CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync(
                $"merge --ff-only --stat --progress {name}", ct);

            if (result.IsFaulted)
            {
                if (result.Error.StartsWith("fatal: Not possible to fast-forward"))
                {
                    Log.Info($"Merge of {name} could not be fast forward merged");
                    return(false);
                }

                return(R.Error($"Failed to ff merge branch {name}", result.AsException()));
            }

            Log.Info($"Merge of {name} was OK");
            return(true);
        }
Esempio n. 28
0
        public async Task <R <string> > GetNoteAsync(string sha, string notesRef, CancellationToken ct)
        {
            CmdResult2 result = await gitCmdService.RunCmdAsync(
                $"-c core.notesRef={notesRef} notes show {sha}", ct);

            if (result.IsFaulted)
            {
                if (result.ExitCode == 1 && result.Error.StartsWith($"error: no note found for object {sha}"))
                {
                    return(R.NoValue);
                }

                return(R.Error("Failed to get note", result.AsException()));
            }

            string notes = result.Output;

            Log.Info($"Got note {notes.Length} length");
            return(notes);
        }
Esempio n. 29
0
        public async Task <R> AddNoteAsync(
            string sha, string notesRef, string note, CancellationToken ct)
        {
            Log.Debug($"Adding {note.Length}chars on {sha} {notesRef} ...");

            string filePath = Path.GetTempFileName();

            File.WriteAllText(filePath, note);
            CmdResult2 result = await gitCmdService.RunCmdAsync(
                $"-c core.notesRef={notesRef} notes add -f --allow-empty -F \"{filePath}\" {sha}", ct);

            DeleteNotesFile(filePath);

            if (result.IsFaulted)
            {
                return(R.Error("Failed to add note", result.AsException()));
            }


            Log.Info($"Added note {note.Length} length");
            return(R.Ok);
        }
Esempio n. 30
0
        public async Task <R> FetchAsync(CancellationToken ct)
        {
            Log.Debug("Fetching ...");

            void Progress(string text)
            {
                Log.Debug($"Progress: {text}");
            }

            CmdResult2 result = await gitCmdService.RunCmdWitProgressAsync(FetchArgs, Progress, ct);

            if (result.IsFaulted)
            {
                if (IsNoRemote(result))
                {
                    return(R.Ok);
                }
                return(R.Error("Failed to fetch", result.AsException()));
            }

            return(R.Ok);
        }