Example #1
0
        static void ProcessHistoryInternal(DXVcsWrapper vcsWrapper, GitWrapper gitWrapper, RegisteredUsers users, User defaultUser, string localGitDir, TrackBranch branch, IList<CommitItem> commits, SyncHistoryWrapper syncHistory) {
            ProjectExtractor extractor = new ProjectExtractor(commits, (item) => {
                var localCommits = vcsWrapper.GetCommits(item.TimeStamp, item.Items).Where(x => !IsLabel(x)).ToList();
                bool hasModifications = false;
                GitCommit last = null;
                string token = syncHistory.CreateNewToken();
                foreach (var localCommit in localCommits) {
                    string localProjectPath = Path.Combine(localGitDir, localCommit.Track.ProjectPath);
                    DirectoryHelper.DeleteDirectory(localProjectPath);
                    string trackPath = branch.GetTrackRoot(localCommit.Track);
                    vcsWrapper.GetProject(vcsServer, trackPath, localProjectPath, item.TimeStamp);

                    Log.Message($"git stage {localCommit.Track.ProjectPath}");
                    gitWrapper.Stage(localCommit.Track.ProjectPath);
                    string author = CalcAuthor(localCommit, defaultUser);
                    var comment = CalcComment(localCommit, author, token);
                    User user = users.GetUser(author);
                    try {
                        gitWrapper.Commit(comment.ToString(), user, localCommit.TimeStamp, false);
                        last = gitWrapper.FindCommit(x => true);
                        hasModifications = true;
                    }
                    catch (Exception) {
                        Log.Message($"Empty commit detected for {localCommit.Author} {localCommit.TimeStamp}.");
                    }
                }
                if (hasModifications) {
                    gitWrapper.PushEverything();
                    syncHistory.Add(last.Sha, item.TimeStamp.Ticks, token);
                }
                else {
                    var head = syncHistory.GetHead();
                    syncHistory.Add(head.GitCommitSha, item.TimeStamp.Ticks, token);
                    string author = CalcAuthor(item, defaultUser);
                    Log.Message($"Push empty commits rejected for {author} {item.TimeStamp}.");
                }
                syncHistory.Save();
            });
            int i = 0;
            while (extractor.PerformExtraction())
                Log.Message($"{++i} from {commits.Count} push to branch {branch.Name} completed.");
        }
Example #2
0
        static IList<CommitItem> GenerateCommits(DXVcsWrapper vcsWrapper, TrackBranch branch, SyncHistoryWrapper syncHistory, bool mergeCommits) {
            DateTime lastCommit = CalcLastCommitDate(syncHistory);
            Log.Message($"Last commit has been performed at {lastCommit.ToLocalTime()}.");

            var history = vcsWrapper.GenerateHistory(branch, lastCommit).OrderBy(x => x.ActionDate).ToList();
            Log.Message($"History generated. {history.Count} history items obtained.");

            IList<CommitItem> commits = vcsWrapper.GenerateCommits(history).Where(x => x.TimeStamp > lastCommit && !IsLabel(x)).ToList();
            if (mergeCommits)
                commits = vcsWrapper.MergeCommits(commits);
            return commits;
        }
Example #3
0
 static DateTime CalcLastCommitDate(SyncHistoryWrapper syncHistory) {
     var head = syncHistory.GetHistoryHead();
     return new DateTime(head.VcsCommitTimeStamp);
 }
Example #4
0
        static MergeRequestResult ProcessOpenedMergeRequest(DXVcsWrapper vcsWrapper, GitWrapper gitWrapper, GitLabWrapper gitLabWrapper, RegisteredUsers users, User defaultUser, string localGitDir, TrackBranch branch, MergeRequest mergeRequest, SyncHistoryWrapper syncHistory) {
            string autoSyncToken = syncHistory.CreateNewToken();
            var lastHistoryItem = syncHistory.GetHead();

            Log.Message($"Start merging mergerequest {mergeRequest.Title}");

            Log.ResetErrorsAccumulator();
            var changes = gitLabWrapper.GetMergeRequestChanges(mergeRequest).ToList();
            if (changes.Count >= MaxChangesCount) {
                Log.Error($"Merge request contains more than {MaxChangesCount} changes and cannot be processed. Split it into smaller merge requests");
                AssignBackConflictedMergeRequest(gitLabWrapper, users, mergeRequest, CalcCommentForFailedCheckoutMergeRequest(null));
                return MergeRequestResult.Failed;
            }
            var genericChange = changes
                .Where(x => branch.TrackItems.FirstOrDefault(track => CheckItemForChangeSet(x, track)) != null)
                .Select(x => ProcessMergeRequestChanges(mergeRequest, x, localGitDir, branch, autoSyncToken)).ToList();
            bool ignoreValidation = gitLabWrapper.ShouldIgnoreSharedFiles(mergeRequest);

            if (!ValidateMergeRequestChanges(gitLabWrapper, mergeRequest, ignoreValidation) || !vcsWrapper.ProcessCheckout(genericChange, ignoreValidation, branch)) {
                Log.Error("Merging merge request failed because failed validation.");
                AssignBackConflictedMergeRequest(gitLabWrapper, users, mergeRequest, CalcCommentForFailedCheckoutMergeRequest(genericChange));
                vcsWrapper.ProcessUndoCheckout(genericChange);
                return MergeRequestResult.CheckoutFailed;
            }
            CommentWrapper comment = CalcComment(mergeRequest, branch, autoSyncToken);
            mergeRequest = gitLabWrapper.ProcessMergeRequest(mergeRequest, comment.ToString());
            if (mergeRequest.State == "merged") {
                Log.Message("Merge request merged successfully.");

                gitWrapper.Pull();
                gitWrapper.LFSPull();

                var gitCommit = gitWrapper.FindCommit(x => CommentWrapper.Parse(x.Message).Token == autoSyncToken);
                long timeStamp = lastHistoryItem.VcsCommitTimeStamp;

                if (gitCommit != null && vcsWrapper.ProcessCheckIn(genericChange, comment.ToString())) {
                    var checkinHistory = vcsWrapper.GenerateHistory(branch, new DateTime(timeStamp)).Where(x => x.ActionDate.Ticks > timeStamp);
                    var lastCommit = checkinHistory.OrderBy(x => x.ActionDate).LastOrDefault();
                    long newTimeStamp = lastCommit?.ActionDate.Ticks ?? timeStamp;
                    var mergeRequestResult = MergeRequestResult.Success;
                    if (!ValidateMergeRequest(vcsWrapper, branch, lastHistoryItem, defaultUser))
                        mergeRequestResult = MergeRequestResult.Mixed;
                    if (!ValidateChangeSet(genericChange))
                        mergeRequestResult = MergeRequestResult.Mixed;
                    syncHistory.Add(gitCommit.Sha, newTimeStamp, autoSyncToken, mergeRequestResult == MergeRequestResult.Success ? SyncHistoryStatus.Success : SyncHistoryStatus.Mixed);
                    syncHistory.Save();
                    Log.Message("Merge request checkin successfully.");
                    return mergeRequestResult;
                }
                Log.Error("Merge request checkin failed.");
                if (gitCommit == null)
                    Log.Error($"Can`t find git commit with token {autoSyncToken}");
                var failedHistory = vcsWrapper.GenerateHistory(branch, new DateTime(timeStamp));
                var lastFailedCommit = failedHistory.OrderBy(x => x.ActionDate).LastOrDefault();
                syncHistory.Add(gitCommit.Sha, lastFailedCommit?.ActionDate.Ticks ?? timeStamp, autoSyncToken, SyncHistoryStatus.Failed);
                syncHistory.Save();
                return MergeRequestResult.Failed;
            }
            Log.Message($"Merge request merging failed due conflicts. Resolve conflicts manually.");
            vcsWrapper.ProcessUndoCheckout(genericChange);
            AssignBackConflictedMergeRequest(gitLabWrapper, users, mergeRequest, CalcCommentForFailedCheckoutMergeRequest(genericChange));

            return MergeRequestResult.Conflicts;
        }
Example #5
0
        static ProcessHistoryResult ProcessHistory(DXVcsWrapper vcsWrapper, GitWrapper gitWrapper, RegisteredUsers users, User defaultUser, string gitRepoPath, string localGitDir, TrackBranch branch, int commitsCount, SyncHistoryWrapper syncHistory, bool mergeCommits) {
            IList<CommitItem> commits = GenerateCommits(vcsWrapper, branch, syncHistory, mergeCommits);

            if (commits.Count > commitsCount) {
                Log.Message($"Commits generated. First {commitsCount} of {commits.Count} commits taken.");
                commits = commits.Take(commitsCount).ToList();
            }
            else {
                Log.Message($"Commits generated. {commits.Count} commits taken.");
            }
            if (commits.Count > 0)
                ProcessHistoryInternal(vcsWrapper, gitWrapper, users, defaultUser, localGitDir, branch, commits, syncHistory);
            Log.Message($"Importing history from vcs completed.");

            return commits.Count > commitsCount ? ProcessHistoryResult.NotEnough : ProcessHistoryResult.Success;
        }
Example #6
0
 static MergeRequestResult ProcessMergeRequest(DXVcsWrapper vcsWrapper, GitWrapper gitWrapper, GitLabWrapper gitLabWrapper, RegisteredUsers users, User defaultUser, string localGitDir, TrackBranch branch, MergeRequest mergeRequest, SyncHistoryWrapper syncHistory) {
     switch (mergeRequest.State) {
         case "reopened":
         case "opened":
             return ProcessOpenedMergeRequest(vcsWrapper, gitWrapper, gitLabWrapper, users, defaultUser, localGitDir, branch, mergeRequest, syncHistory);
     }
     return MergeRequestResult.InvalidState;
 }
Example #7
0
 static int ProcessMergeRequests(DXVcsWrapper vcsWrapper, GitWrapper gitWrapper, GitLabWrapper gitLabWrapper, RegisteredUsers users, User defaultUser, string gitRepoPath, string localGitDir, string branchName, string tracker, SyncHistoryWrapper syncHistory, string userName) {
     var project = gitLabWrapper.FindProject(gitRepoPath);
     TrackBranch branch = GetBranch(branchName, tracker, vcsWrapper);
     if (branch == null) {
         Log.Error($"Specified branch {branchName} not found in track file.");
         return 1;
     }
     var mergeRequests = GetMergeRequests(gitLabWrapper, branchName, userName, project);
     if (!mergeRequests.Any()) {
         Log.Message("Zero registered merge requests.");
         return 0;
     }
     int result = 0;
     foreach (var mergeRequest in mergeRequests) {
         var mergeRequestResult = ProcessMergeRequest(vcsWrapper, gitWrapper, gitLabWrapper, users, defaultUser, localGitDir, branch, mergeRequest, syncHistory);
         if (mergeRequestResult == MergeRequestResult.Failed)
             return 1;
         if (mergeRequestResult == MergeRequestResult.CheckoutFailed || mergeRequestResult == MergeRequestResult.Conflicts || mergeRequestResult == MergeRequestResult.InvalidState)
             result = 1;
     }
     return result;
 }
Example #8
0
        static CheckMergeChangesResult CheckChangesForMerging(GitLabWrapper gitLabWrapper, string gitRepoPath, string branchName, SyncHistoryItem head, DXVcsWrapper vcsWrapper, TrackBranch branch, SyncHistoryWrapper syncHistory, User defaultUser) {
            var project = gitLabWrapper.FindProject(gitRepoPath);
            if (project == null) {
                Log.Error($"Can`t find git project {gitRepoPath}");
                return CheckMergeChangesResult.Error;
            }

            var gitlabBranch = gitLabWrapper.GetBranches(project).Single(x => x.Name == branchName);
            if (gitlabBranch.Commit.Id.Equals(new Sha1(head.GitCommitSha))) {
                var commits = GenerateCommits(vcsWrapper, branch, syncHistory, false);
                if (commits.Count == 0) {
                    var mergeRequests = GetMergeRequests(gitLabWrapper, branchName, defaultUser.UserName, project);
                    if (!mergeRequests.Any()) {
                        Log.Message("Zero registered merge requests.");
                        return CheckMergeChangesResult.NoChanges;
                    }
                }
            }
            return CheckMergeChangesResult.HasChanges;
        }
Example #9
0
        static int DoSyncWork(SyncOptions clo) {
            string localGitDir = clo.LocalFolder != null && Path.IsPathRooted(clo.LocalFolder) ? clo.LocalFolder : Path.Combine(Environment.CurrentDirectory, clo.LocalFolder ?? repoPath);
            EnsureGitDir(localGitDir);

            string gitRepoPath = clo.Repo;
            string username = clo.Login;
            string password = clo.Password;
            string gitlabauthtoken = clo.AuthToken;
            string branchName = clo.Branch;
            string trackerPath = clo.Tracker;
            string gitServer = clo.Server;

            DXVcsWrapper vcsWrapper = new DXVcsWrapper(vcsServer, username, password);

            TrackBranch branch = FindBranch(branchName, trackerPath, vcsWrapper);
            if (branch == null)
                return 1;

            string historyPath = GetVcsSyncHistory(vcsWrapper, branch.HistoryPath);
            if (historyPath == null)
                return 1;
            SyncHistory history = SyncHistory.Deserialize(historyPath);
            if (history == null)
                return 1;

            SyncHistoryWrapper syncHistory = new SyncHistoryWrapper(history, vcsWrapper, branch.HistoryPath, historyPath);
            var head = syncHistory.GetHistoryHead();
            if (head == null)
                return 1;

            GitLabWrapper gitLabWrapper = new GitLabWrapper(gitServer, gitlabauthtoken);
            RegisteredUsers registeredUsers = new RegisteredUsers(gitLabWrapper, vcsWrapper);
            User defaultUser = registeredUsers.GetUser(username);
            if (!defaultUser.IsRegistered) {
                Log.Error($"default user {username} is not registered in the active directory.");
                return 1;
            }
            var checkMergeChangesResult = CheckChangesForMerging(gitLabWrapper, gitRepoPath, branchName, head, vcsWrapper, branch, syncHistory, defaultUser);
            if (checkMergeChangesResult == CheckMergeChangesResult.NoChanges)
                return 0;
            if (checkMergeChangesResult == CheckMergeChangesResult.Error)
                return 1;

            GitWrapper gitWrapper = CreateGitWrapper(gitRepoPath, localGitDir, branch.Name, username, password);
            if (gitWrapper == null)
                return 1;

            ProcessHistoryResult processHistoryResult = ProcessHistory(vcsWrapper, gitWrapper, registeredUsers, defaultUser, gitRepoPath, localGitDir, branch, clo.CommitsCount, syncHistory, true);
            if (processHistoryResult == ProcessHistoryResult.NotEnough)
                return 0;
            if (processHistoryResult == ProcessHistoryResult.Failed)
                return 1;

            int result = ProcessMergeRequests(vcsWrapper, gitWrapper, gitLabWrapper, registeredUsers, defaultUser, gitRepoPath, localGitDir, clo.Branch, clo.Tracker, syncHistory, username);
            if (result != 0)
                return result;
            return 0;
        }
Example #10
0
        static int DoPatchWork(PatchOptions clo) {
            string localGitDir = clo.LocalFolder != null && Path.IsPathRooted(clo.LocalFolder) ? clo.LocalFolder : Path.Combine(Environment.CurrentDirectory, clo.LocalFolder ?? repoPath);

            string targetRepoPath = GetSimpleGitHttpPath(clo.Repo);

            if (string.IsNullOrEmpty(targetRepoPath)) {
                Log.Error($"Can`t parse repo path {clo.Repo}");
                return 1;
            }
            string sourceRepoPath = GetSimpleGitHttpPath(clo.SourceRepo);
            if (string.IsNullOrEmpty(sourceRepoPath)) {
                Log.Error($"Can`t parse source repo path {clo.SourceRepo}");
                return 1;
            }

            string username = clo.Login;
            string password = clo.Password;
            string gitlabauthtoken = clo.AuthToken;
            string targetBranchName = clo.Branch;
            string trackerPath = clo.Tracker;
            string gitServer = clo.Server;
            string sourceBranchName = clo.SourceBranch;
            string patchdir = clo.PatchDir ?? localGitDir;

            DXVcsWrapper vcsWrapper = new DXVcsWrapper(vcsServer, username, password);

            TrackBranch trackBranch = FindBranch(targetBranchName, trackerPath, vcsWrapper);
            if (trackBranch == null) {
                return 1;
            }

            string historyPath = GetVcsSyncHistory(vcsWrapper, trackBranch.HistoryPath);
            if (historyPath == null)
                return 1;
            SyncHistory history = SyncHistory.Deserialize(historyPath);
            if (history == null)
                return 1;

            SyncHistoryWrapper syncHistory = new SyncHistoryWrapper(history, vcsWrapper, trackBranch.HistoryPath, historyPath);
            var head = syncHistory.GetHistoryHead();
            if (head == null)
                return 1;

            GitLabWrapper gitLabWrapper = new GitLabWrapper(gitServer, gitlabauthtoken);

            Project targetProject = gitLabWrapper.FindProject(targetRepoPath);
            if (targetProject == null) {
                Log.Error($"Can`t find target project {targetRepoPath}.");
                return 1;
            }
            Log.Message($"Target project url: {targetProject.HttpUrl}");

            Branch targetBranch = gitLabWrapper.GetBranch(targetProject, targetBranchName);
            if (targetBranch == null) {
                Log.Error($"Can`t find targetBranch branch {targetBranchName}");
                return 1;
            }
            Log.Message($"Target branch name: {targetBranch.Name}");

            var sourceProject = gitLabWrapper.FindProjectFromAll(sourceRepoPath);
            if (sourceProject == null) {
                Log.Error($"Can`t find source project {sourceRepoPath}");
                return 1;
            }
            Log.Message($"Source project url: {sourceProject.HttpUrl}");

            var sourceBranch = gitLabWrapper.GetBranch(sourceProject, sourceBranchName);
            if (sourceBranch == null) {
                Log.Error($"Source branch {sourceBranchName} was not found.");
                return 1;
            }
            Log.Message($"Target branch name: {sourceBranch.Name}");

            MergeRequest mergeRequest = gitLabWrapper.GetMergeRequests(targetProject, 
                x => x.SourceBranch == sourceBranchName && x.TargetBranch == targetBranchName && x.SourceProjectId == sourceProject.Id).FirstOrDefault();
            if (mergeRequest == null) {
                Log.Error($"Can`t find merge request.");
                return 1;
            }
            Log.Message($"Merge request id: {mergeRequest.Id}.");
            Log.Message($"Merge request title: {mergeRequest.Title}.");

            var comments = gitLabWrapper.GetComments(mergeRequest);
            var mergeRequestSyncOptions = comments?.Where(x => IsXml(x.Note)).Where(x => {
                var mr = MergeRequestOptions.ConvertFromString(x.Note);
                return mr?.ActionType == MergeRequestActionType.sync;
            }).Select(x => (MergeRequestSyncAction)MergeRequestOptions.ConvertFromString(x.Note).Action).LastOrDefault();

            if (mergeRequest.Assignee?.Name != username || (!mergeRequestSyncOptions?.PerformTesting ?? false)) {
                Log.Error($"Merge request is not assigned to service user {username} or doesn`t require testing.");
                return 1;
            }

            GitWrapper gitWrapper = CreateGitWrapper(sourceRepoPath, localGitDir, sourceBranchName, username, password);
            if (gitWrapper == null) {
                Log.Error("Can`t create git wrapper.");
                return 1;
            }

            var changes = gitLabWrapper
                .GetMergeRequestChanges(mergeRequest)
                .Where(x => trackBranch.TrackItems.FirstOrDefault(track => CheckItemForChangeSet(x, track)) != null)
                .Select(x => new PatchItem() {
                    SyncAction = CalcSyncAction(x),
                    OldPath = x.OldPath,
                    NewPath = x.NewPath,
                    OldVcsPath = CalcVcsPath(trackBranch, x.OldPath),
                    NewVcsPath = CalcVcsPath(trackBranch, x.NewPath),
                }).ToList();

            var patch = new PatchInfo() { TimeStamp = DateTime.Now.Ticks, Items = changes };

            var patchPath = Path.Combine(patchdir, patchZip);
            using (Package zip = Package.Open(patchPath, FileMode.Create)) {
                SavePatchInfo(patchdir, patch);
                AddPart(zip, patchdir, "patch.info");
                foreach (var path in CalcFilesForPatch(patch)) {
                    AddPart(zip, localGitDir, path);
                }
            }

            Log.Message($"Patch.info generated at {patchPath}");
            return 0;
        }