Tracks the names and locations of VSS projects and files as revisions are replayed.
コード例 #1
0
        private bool ReplayRevisionAlt(Revision revision,
                                       GitWrapper git, LinkedList <Revision> labels)
        {
            var needCommit = false;
            var actionType = revision.Action.Type;

            // We don't worry about projects! <smile>
            if (
                (!revision.Item.IsProject)
                &&
                (actionType == VssActionType.Create) || (actionType == VssActionType.Edit)
                )
            {
                FileLocation fileLocation;
                if (fileAnalyzer.SortedFileLocations.TryGetValue(revision.Item.PhysicalName, out fileLocation))
                {
                    var path = VssPathMapper.GetWorkingPath(repoPath, fileLocation.Path, inheritProjectDir ? "" : fileAnalyzer.vssRootProjectPath);
                    logger.WriteLine("{0}: {1} revision {2}", fileLocation.Path, actionType, revision.Version);
                    if (WriteRevisionTo(revision.Item.PhysicalName, revision.Version, path))
                    {
                        // add file explicitly, so it is visible to subsequent git operations
                        git.Add(path);
                        needCommit = true;
                    }
                }
            }
            return(needCommit);
        }
コード例 #2
0
        private bool ReplayChangeset(VssPathMapper pathMapper, Changeset changeset,
                                     GitWrapper git, LinkedList <Revision> labels)
        {
            var needCommit = false;

            foreach (Revision revision in changeset.Revisions)
            {
                if (workQueue.IsAborting)
                {
                    break;
                }

                AbortRetryIgnore(delegate
                {
                    if (fileAnalyzer == null)
                    {
                        needCommit |= ReplayRevision(pathMapper, revision, git, labels);
                    }
                    else
                    {
                        needCommit |= ReplayRevisionAlt(revision, git, labels);
                    }
                });
            }
            return(needCommit);
        }
コード例 #3
0
ファイル: VcsExporter.cs プロジェクト: pokke123/vss2git
 private void SkipChangeset(VssPathMapper pathMapper, Changeset changeset)
 {
     foreach (Revision revision in changeset.Revisions)
     {
         if (workQueue.IsAborting)
         {
             break;
         }
         SkipRevision(pathMapper, revision);
     }
 }
コード例 #4
0
ファイル: VcsExporter.cs プロジェクト: pokke123/vss2git
        private void ReplayChangeset(VssPathMapper pathMapper, Changeset changeset,
                                     LinkedList <Revision> labels)
        {
            foreach (Revision revision in changeset.Revisions)
            {
                if (workQueue.IsAborting)
                {
                    break;
                }

                AbortRetryIgnore(delegate
                {
                    ReplayRevision(pathMapper, revision, labels);
                });
            }
        }
コード例 #5
0
        private bool WriteRevision(VssPathMapper pathMapper, VssActionType actionType,
                                   string physicalName, int version, string underProject, GitWrapper git)
        {
            var needCommit = false;
            var paths      = pathMapper.GetFilePaths(physicalName, underProject);

            foreach (string path in paths)
            {
                logger.WriteLine("{0}: {1} revision {2}", path, actionType, version);
                if (WriteRevisionTo(physicalName, version, path))
                {
                    // add file explicitly, so it is visible to subsequent git operations
                    git.Add(path);
                    needCommit = true;
                }
            }
            return(needCommit);
        }
コード例 #6
0
ファイル: VcsExporter.cs プロジェクト: pokke123/vss2git
        private void WriteRevision(VssPathMapper pathMapper, VssActionType actionType,
                                   string physicalName, int version, string underProject)
        {
            var paths = pathMapper.GetFilePaths(physicalName, underProject);

            if (!paths.Any())
            {
                logger.WriteLine("WARNING: {0}: no physical path, {1} revision {2} skipped", physicalName, actionType, version);
            }
            foreach (string path in paths)
            {
                logger.WriteLine("{0}: {1} revision {2}", path, actionType, version);
                if (WriteRevisionTo(physicalName, version, path))
                {
                    // add file explicitly, so it is visible to subsequent vcs operations
                    vcsWrapper.Add(path);
                }
            }
        }
コード例 #7
0
ファイル: VcsExporter.cs プロジェクト: pokke123/vss2git
        public void ExportToVcs(string repoPath, DateTime?continueAfter)
        {
            if (resetRepo)
            {
                continueAfter = null;
            }
            this.continueAfter = continueAfter;
            workQueue.AddLast(delegate(object work)
            {
                var stopwatch = Stopwatch.StartNew();

                logger.WriteSectionSeparator();
                LogStatus(work, "Initializing repository");

                // create repository directory if it does not exist
                if (!Directory.Exists(repoPath))
                {
                    if (continueAfter != null)
                    {
                        throw new ProcessException("Unable to continue: " + repoPath + " does not exist.", null, null);
                    }
                    Directory.CreateDirectory(repoPath);
                }

                string vcs = vcsWrapper.GetVcs();

                while (!vcsWrapper.FindExecutable())
                {
                    var button = MessageBox.Show(vcs + " not found in PATH. " +
                                                 "If you need to modify your PATH variable, please " +
                                                 "restart the program for the changes to take effect.",
                                                 "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                    if (button == DialogResult.Cancel)
                    {
                        workQueue.Abort();
                        return;
                    }
                }

                bool makeInitialCommit = resetRepo;
                if (!RetryCancel(delegate
                                 { vcsWrapper.Init(resetRepo); }))
                {
                    return;
                }

                AbortRetryIgnore(delegate
                {
                    vcsWrapper.Configure(continueAfter == null);
                });

                var pathMapper = new VssPathMapper();

                if (UseProjectsFile)
                {
                    string rootPath = repoPath;
                    foreach (var rootProject in revisionAnalyzer.RootProjects)
                    {
                        string path = rootProject.RootPath;
                        path        = path.Replace("/", "\\");
                        if (path.StartsWith("\\"))
                        {
                            path = rootPath + path;
                        }
                        else
                        {
                            path = rootPath + "\\" + path;
                        }
                        pathMapper.SetProjectPath(rootProject.PhysicalName, path, rootProject.Path);
                    }
                }
                else
                {
                    // create mappings for root projects
                    foreach (var rootProject in revisionAnalyzer.RootProjects)
                    {
                        // root must be repo path here - the path mapper uses paths relative to this one
                        VssPathMapper vssPathMapper = new VssPathMapper();
                        var rootPath = repoPath;
                        if (RemovePath != "")
                        {
                            if (rootProject.Path.StartsWith(RemovePath))
                            {
                                string path = rootProject.Path.Replace(RemovePath, "");
                                path        = path.Replace("/", "\\");
                                if (path.StartsWith("\\"))
                                {
                                    rootPath = rootPath + path;
                                }
                                else
                                {
                                    rootPath = rootPath + "\\" + path;
                                }
                            }
                            else
                            {
                                var button = MessageBox.Show($"{RemovePath} not found in path, Do you wanne continue with all contint in the root folder.",
                                                             "Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
                                if (button == DialogResult.Cancel)
                                {
                                    workQueue.Abort();
                                    return;
                                }
                            }
                        }


                        pathMapper.SetProjectPath(rootProject.PhysicalName, rootPath, rootProject.Path);
                    }
                }
                var changesets = changesetBuilder.Changesets;

                // create a log of all MoveFrom and MoveTo actions
                logger.WriteSectionSeparator();
                logger.WriteLine("List of Move Operations");
                logger.WriteSectionSeparator();

                int changeSetNo = 0;
                int revisionNo  = 0;
                foreach (var changeset in changesets)
                {
                    foreach (var revision in changeset.Revisions)
                    {
                        var actionType     = revision.Action.Type;
                        VssItemName target = null;
                        var namedAction    = revision.Action as VssNamedAction;
                        if (namedAction != null)
                        {
                            target = namedAction.Name;
                        }

                        switch (actionType)
                        {
                        case VssActionType.MoveFrom:
                            var moveFromAction = (VssMoveFromAction)revision.Action;
                            logger.WriteLine("{3}-{4}-{0}: MoveFrom {1} to {2}",
                                             revision.Item, moveFromAction.OriginalProject, target, changeSetNo, revisionNo);
                            break;

                        case VssActionType.MoveTo:
                            var moveToAction = (VssMoveToAction)revision.Action;
                            logger.WriteLine("{3}-{4}-{0}: MoveTo {1} from {2}",
                                             revision.Item, moveToAction.NewProject, target, changeSetNo, revisionNo);
                            break;
                        }
                        revisionNo++;
                    }
                    changeSetNo++;
                    //AdvancedTaskbar.SetPosition((uint)changeSetNo);
                }

                // replay each changeset
                logger.WriteSectionSeparator();
                logger.WriteLine("Replaying Changesets");

                var changesetId     = 0;
                var commitCount     = 0;
                var tagCount        = 0;
                var replayStopwatch = new Stopwatch();
                var labels          = new LinkedList <Revision>();
                tagsUsed.Clear();

                bool found = continueAfter == null;

                foreach (var changeset in changesets)
                {
                    ++changesetId;
                    if (workQueue.IsAborting)
                    {
                        return;
                    }

                    if (!found)
                    {
                        if (continueAfter.Equals(changeset.DateTime))
                        {
                            found = true;
                        }
                        SkipChangeset(pathMapper, changeset);
                        continue;
                    }

                    var changesetDesc = string.Format("changeset {0} from {1:yyyy-MM-dd HH:mm:ss}", changesetId, changeset.DateTime);

                    // replay each revision in changeset
                    logger.WriteSectionSeparator();
                    LogStatus(work, "Replaying " + changesetDesc);
                    labels.Clear();
                    replayStopwatch.Start();
                    try
                    {
                        ReplayChangeset(pathMapper, changeset, labels);
                        if (makeInitialCommit)
                        {
                            vcsWrapper.Init(changeset, repoPath);
                            makeInitialCommit = false;
                        }
                        vcsWrapper.NeedsCommit(); // to flush outstanding adds/deletes
                    }
                    finally
                    {
                        replayStopwatch.Stop();
                    }

                    if (workQueue.IsAborting)
                    {
                        return;
                    }

                    // commit changes
                    if (vcsWrapper.NeedsCommit())
                    {
                        LogStatus(work, "Committing " + changesetDesc);
                        if (CommitChangeset(changeset))
                        {
                            ++commitCount;
                        }
                    }

                    // create tags for any labels in the changeset
                    if (labels.Count > 0)
                    {
                        foreach (Revision label in labels)
                        {
                            var labelName = ((VssLabelAction)label.Action).Label;
                            if (string.IsNullOrEmpty(labelName))
                            {
                                logger.WriteLine("NOTE: Ignoring empty label");
                            }
                            else if (commitCount == 0)
                            {
                                logger.WriteLine("NOTE: Ignoring label '{0}' before initial commit", labelName);
                            }
                            else
                            {
                                //Datell B.V. Specific operation of adding folder structure to label.
                                //It is optional by using the checkbox
                                if (FolderBeforeLabel && label.Item.IsProject)
                                {
                                    labelName = pathMapper.GetProjectPath(label.Item.PhysicalName) + "_" + labelName;
                                    labelName = labelName.Replace(repoPath, "").TrimStart('\\');
                                }

                                var tagName = GetTagFromLabel(labelName);

                                var tagMessage = "Creating tag " + tagName;
                                if (tagName != labelName)
                                {
                                    tagMessage += " for label '" + labelName + "'";
                                }
                                LogStatus(work, tagMessage);

                                // tags always get a tag message;
                                var tagComment = label.Comment;
                                if (string.IsNullOrEmpty(tagComment))
                                {
                                    // use the original VSS label as the tag message if none was provided
                                    tagComment = labelName;
                                }

                                if (AbortRetryIgnore(
                                        delegate
                                {
                                    vcsWrapper.Tag(tagName, label.User, GetEmail(label.User),
                                                   tagComment, label.DateTime);
                                }))
                                {
                                    ++tagCount;
                                }
                            }
                        }
                    }
                    AdvancedTaskbar.SetPosition((uint)changesetId);
                }

                stopwatch.Stop();

                if (!found)
                {
                    logger.WriteLine("Cannot Sync: VSS changeset at {0} not found.", continueAfter);
                    throw new ProcessException(string.Format("Cannot Sync: VSS changeset at {0} not found.", continueAfter), null, null);
                }

                logger.WriteSectionSeparator();
                logger.WriteLine(vcs + " export complete in {0:HH:mm:ss}", new DateTime(stopwatch.ElapsedTicks));
                logger.WriteLine("Replay time: {0:HH:mm:ss}", new DateTime(replayStopwatch.ElapsedTicks));
                logger.WriteLine(vcs + " time: {0:HH:mm:ss}", new DateTime(vcsWrapper.ElapsedTime().Ticks));
                logger.WriteLine(vcs + " commits: {0}", commitCount);
                logger.WriteLine(vcs + " tags: {0}", tagCount);
            });
        }
コード例 #8
0
ファイル: GitExporter.cs プロジェクト: runt18/vss2git-1
        public void ExportToGit(string repoPath)
        {
            workQueue.AddLast(delegate(object work)
            {
                var stopwatch = Stopwatch.StartNew();

                logger.WriteSectionSeparator();
                LogStatus(work, "Initializing Git repository");

                // create repository directory if it does not exist
                if (!Directory.Exists(repoPath))
                {
                    Directory.CreateDirectory(repoPath);
                }

                var git = new GitWrapper(repoPath, logger);
                git.CommitEncoding = commitEncoding;

                while (!git.FindExecutable())
                {
                    var button = MessageBox.Show("Git not found in PATH. " +
                        "If you need to modify your PATH variable, please " +
                        "restart the program for the changes to take effect.",
                        "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                    if (button == DialogResult.Cancel)
                    {
                        workQueue.Abort();
                        return;
                    }
                }

                if (!RetryCancel(delegate { git.Init(); }))
                {
                    return;
                }

                if (commitEncoding.WebName != "utf-8")
                {
                    AbortRetryIgnore(delegate
                    {
                        git.SetConfig("i18n.commitencoding", commitEncoding.WebName);
                    });
                }

                var pathMapper = new VssPathMapper();

                // create mappings for root projects
                foreach (var rootProject in revisionAnalyzer.RootProjects)
                {
                    var rootPath = VssPathMapper.GetWorkingPath(repoPath, rootProject.Path);
                    pathMapper.SetProjectPath(rootProject.PhysicalName, rootPath, rootProject.Path);
                }

                // replay each changeset
                var changesetId = 1;
                var changesets = changesetBuilder.Changesets;
                var commitCount = 0;
                var tagCount = 0;
                var replayStopwatch = new Stopwatch();
                var labels = new LinkedList<Revision>();
                tagsUsed.Clear();
                foreach (var changeset in changesets)
                {
                    var changesetDesc = string.Format(CultureInfo.InvariantCulture,
                        "changeset {0} from {1}", changesetId, changeset.DateTime);

                    // replay each revision in changeset
                    LogStatus(work, "Replaying " + changesetDesc);
                    labels.Clear();
                    replayStopwatch.Start();
                    bool needCommit;
                    try
                    {
                        needCommit = ReplayChangeset(pathMapper, changeset, git, labels);
                    }
                    finally
                    {
                        replayStopwatch.Stop();
                    }

                    if (workQueue.IsAborting)
                    {
                        return;
                    }

                    // commit changes
                    if (needCommit)
                    {
                        LogStatus(work, "Committing " + changesetDesc);
                        if (CommitChangeset(git, changeset))
                        {
                            ++commitCount;
                        }
                    }

                    if (workQueue.IsAborting)
                    {
                        return;
                    }

                    // create tags for any labels in the changeset
                    if (labels.Count > 0)
                    {
                        foreach (Revision label in labels)
                        {
                            var labelName = ((VssLabelAction)label.Action).Label;
                            if (string.IsNullOrEmpty(labelName))
                            {
                                logger.WriteLine("NOTE: Ignoring empty label");
                            }
                            else if (commitCount == 0)
                            {
                                logger.WriteLine("NOTE: Ignoring label '{0}' before initial commit", labelName);
                            }
                            else
                            {
                                var tagName = GetTagFromLabel(labelName);

                                var tagMessage = "Creating tag " + tagName;
                                if (tagName != labelName)
                                {
                                    tagMessage += " for label '" + labelName + "'";
                                }
                                LogStatus(work, tagMessage);

                                // annotated tags require (and are implied by) a tag message;
                                // tools like Mercurial's git converter only import annotated tags
                                var tagComment = label.Comment;
                                if (string.IsNullOrEmpty(tagComment) && forceAnnotatedTags)
                                {
                                    // use the original VSS label as the tag message if none was provided
                                    tagComment = labelName;
                                }

                                if (AbortRetryIgnore(
                                    delegate
                                    {
                                        git.Tag(tagName, label.User, GetEmail(label.User),
                                            tagComment, label.DateTime);
                                    }))
                                {
                                    ++tagCount;
                                }
                            }
                        }
                    }

                    ++changesetId;
                }

                stopwatch.Stop();

                logger.WriteSectionSeparator();
                logger.WriteLine("Git export complete in {0:HH:mm:ss}", new DateTime(stopwatch.ElapsedTicks));
                logger.WriteLine("Replay time: {0:HH:mm:ss}", new DateTime(replayStopwatch.ElapsedTicks));
                logger.WriteLine("Git time: {0:HH:mm:ss}", new DateTime(git.ElapsedTime.Ticks));
                logger.WriteLine("Git commits: {0}", commitCount);
                logger.WriteLine("Git tags: {0}", tagCount);
            });
        }
コード例 #9
0
ファイル: GitExporter.cs プロジェクト: runt18/vss2git-1
        private bool ReplayChangeset(VssPathMapper pathMapper, Changeset changeset,
            GitWrapper git, LinkedList<Revision> labels)
        {
            var needCommit = false;
            foreach (Revision revision in changeset.Revisions)
            {
                if (workQueue.IsAborting)
                {
                    break;
                }

                AbortRetryIgnore(delegate
                {
                    needCommit |= ReplayRevision(pathMapper, revision, git, labels);
                });
            }
            return needCommit;
        }
コード例 #10
0
ファイル: VcsExporter.cs プロジェクト: rustyx/vss2git
 private void WriteRevision(VssPathMapper pathMapper, VssActionType actionType,
     string physicalName, int version, string underProject)
 {
     var paths = pathMapper.GetFilePaths(physicalName, underProject);
     if (!paths.Any())
     {
         logger.WriteLine("WARNING: {0}: no physical path, {1} revision {2} skipped", physicalName, actionType, version);
     }
     foreach (string path in paths)
     {
         logger.WriteLine("{0}: {1} revision {2}", path, actionType, version);
         if (WriteRevisionTo(physicalName, version, path))
         {
             // add file explicitly, so it is visible to subsequent vcs operations
             vcsWrapper.Add(path);
         }
     }
 }
コード例 #11
0
ファイル: VcsExporter.cs プロジェクト: rustyx/vss2git
        private void SkipRevision(VssPathMapper pathMapper, Revision revision)
        {
            var actionType = revision.Action.Type;
            if (revision.Item.IsProject)
            {
                var project = revision.Item;
                var projectPath = pathMapper.GetProjectPath(project.PhysicalName);

                VssItemName target = null;
                string targetPath = null;
                var namedAction = revision.Action as VssNamedAction;
                if (namedAction != null)
                {
                    target = namedAction.Name;
                    if (projectPath != null)
                    {
                        targetPath = Path.Combine(projectPath, target.LogicalName);
                    }
                }

                switch (actionType)
                {
                    case VssActionType.Add:
                    case VssActionType.Share:
                        pathMapper.AddItem(project, target);
                        break;

                    case VssActionType.Recover:
                        pathMapper.RecoverItem(project, target);
                        break;

                    case VssActionType.Delete:
                    case VssActionType.Destroy:
                        pathMapper.DeleteItem(project, target);
                        break;

                    case VssActionType.Rename:
                        pathMapper.RenameItem(target);
                        break;

                    case VssActionType.MoveFrom:
                        {
                            var moveFromAction = (VssMoveFromAction)revision.Action;
                            var isInside = pathMapper.IsInRoot(moveFromAction.OriginalProject);

                            if (isInside)
                            {
                                pathMapper.MoveProjectFrom(project, target, moveFromAction.OriginalProject);
                            }
                            else
                            {
                                pathMapper.RecoverItem(project, target);
                            }
                        }
                        break;

                    case VssActionType.MoveTo:
                        {
                            var moveToAction = (VssMoveToAction)revision.Action;
                            var isInside = pathMapper.IsInRoot(moveToAction.NewProject);
                            if (!isInside)
                            {
                                pathMapper.DeleteItem(project, target);
                            }
                        }
                        break;

                    case VssActionType.Pin:
                        {
                            var pinAction = (VssPinAction)revision.Action;
                            if (pinAction.Pinned)
                            {
                                pathMapper.PinItem(project, target);
                            }
                            else
                            {
                                pathMapper.UnpinItem(project, target);
                            }
                        }
                        break;

                    case VssActionType.Branch:
                        {
                            var branchAction = (VssBranchAction)revision.Action;
                            pathMapper.BranchFile(project, target, branchAction.Source);
                        }
                        break;

                    case VssActionType.Restore:
                        pathMapper.AddItem(project, target);
                        break;
                }
            }
            // item is a file, not a project
            else if (actionType == VssActionType.Edit || actionType == VssActionType.Branch)
            {
                pathMapper.SetFileVersion(revision.Item, revision.Version);
            }
        }
コード例 #12
0
ファイル: VcsExporter.cs プロジェクト: rustyx/vss2git
 private void SkipChangeset(VssPathMapper pathMapper, Changeset changeset)
 {
     foreach (Revision revision in changeset.Revisions)
     {
         if (workQueue.IsAborting)
         {
             break;
         }
         SkipRevision(pathMapper, revision);
     }
 }
コード例 #13
0
ファイル: VcsExporter.cs プロジェクト: rustyx/vss2git
        private void ReplayChangeset(VssPathMapper pathMapper, Changeset changeset,
            LinkedList<Revision> labels)
        {
            foreach (Revision revision in changeset.Revisions)
            {
                if (workQueue.IsAborting)
                {
                    break;
                }

                AbortRetryIgnore(delegate
                {
                    ReplayRevision(pathMapper, revision, labels);
                });
            }
        }
コード例 #14
0
ファイル: VcsExporter.cs プロジェクト: rustyx/vss2git
        public void ExportToVcs(string repoPath, DateTime? continueAfter)
        {
            this.continueAfter = continueAfter;
            workQueue.AddLast(delegate(object work)
            {
                var stopwatch = Stopwatch.StartNew();

                logger.WriteSectionSeparator();
                LogStatus(work, "Initializing repository");

                if (continueAfter != null && resetRepo)
                    throw new ProcessException("Unable to continue sync and reset repo at the same time!", null, null);
                // create repository directory if it does not exist
                if (!Directory.Exists(repoPath))
                {
                    if (continueAfter != null)
                        throw new ProcessException("Unable to continue: " + repoPath + " does not exist.", null, null);
                    Directory.CreateDirectory(repoPath);
                }

                string vcs = vcsWrapper.GetVcs();

                while (!vcsWrapper.FindExecutable())
                {
                    var button = MessageBox.Show(vcs + " not found in PATH. " +
                        "If you need to modify your PATH variable, please " +
                        "restart the program for the changes to take effect.",
                        "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                    if (button == DialogResult.Cancel)
                    {
                        workQueue.Abort();
                        return;
                    }
                }

                if (!RetryCancel(delegate { vcsWrapper.Init(resetRepo); }))
                {
                    return;
                }

                AbortRetryIgnore(delegate
                {
                    vcsWrapper.Configure(continueAfter == null);
                });

                var pathMapper = new VssPathMapper();

                // create mappings for root projects
                foreach (var rootProject in revisionAnalyzer.RootProjects)
                {
                    // root must be repo path here - the path mapper uses paths relative to this one
                    var rootPath = repoPath;
                    pathMapper.SetProjectPath(rootProject.PhysicalName, rootPath, rootProject.Path);
                }

                var changesets = changesetBuilder.Changesets;

                // create a log of all MoveFrom and MoveTo actions
                logger.WriteSectionSeparator();
                logger.WriteLine("List of Move Operations");
                logger.WriteSectionSeparator();

                int changeSetNo = 0;
                int revisionNo = 0;
                foreach (var changeset in changesets)
                {
                    foreach (var revision in changeset.Revisions)
                    {
                        var actionType = revision.Action.Type;
                        VssItemName target = null;
                        var namedAction = revision.Action as VssNamedAction;
                        if (namedAction != null)
                        {
                            target = namedAction.Name;
                        }

                        switch (actionType)
                        {
                            case VssActionType.MoveFrom:
                                var moveFromAction = (VssMoveFromAction)revision.Action;
                                logger.WriteLine("{3}-{4}-{0}: MoveFrom {1} to {2}",
                                    revision.Item, moveFromAction.OriginalProject, target, changeSetNo, revisionNo);
                                break;
                            case VssActionType.MoveTo:
                                var moveToAction = (VssMoveToAction)revision.Action;
                                logger.WriteLine("{3}-{4}-{0}: MoveTo {1} from {2}",
                                    revision.Item, moveToAction.NewProject, target, changeSetNo, revisionNo);
                                break;
                        }
                        revisionNo++;
                    }
                    changeSetNo++;
                }

                // replay each changeset
                logger.WriteSectionSeparator();
                logger.WriteLine("Replaying Changesets");

                var changesetId = 0;
                var commitCount = 0;
                var tagCount = 0;
                var replayStopwatch = new Stopwatch();
                var labels = new LinkedList<Revision>();
                tagsUsed.Clear();

                bool found = continueAfter == null;

                foreach (var changeset in changesets)
                {
                    ++changesetId;
                    if (workQueue.IsAborting)
                    {
                        return;
                    }

                    if (!found)
                    {
                        if (continueAfter.Equals(changeset.DateTime))
                            found = true;
                        SkipChangeset(pathMapper, changeset);
                        continue;
                    }

                    var changesetDesc = string.Format(CultureInfo.InvariantCulture,
                        "changeset {0} from {1}", changesetId, changeset.DateTime);

                    // replay each revision in changeset
                    logger.WriteSectionSeparator();
                    LogStatus(work, "Replaying " + changesetDesc);
                    labels.Clear();
                    replayStopwatch.Start();
                    try
                    {
                        ReplayChangeset(pathMapper, changeset, labels);
                        vcsWrapper.NeedsCommit(); // to flush outstanding adds/deletes
                    }
                    finally
                    {
                        replayStopwatch.Stop();
                    }

                    if (workQueue.IsAborting)
                    {
                        return;
                    }

                    // commit changes
                    if (vcsWrapper.NeedsCommit())
                    {
                        LogStatus(work, "Committing " + changesetDesc);
                        if (CommitChangeset(changeset))
                        {
                            ++commitCount;
                        }
                    }

                    // create tags for any labels in the changeset
                    if (labels.Count > 0)
                    {
                        foreach (Revision label in labels)
                        {
                            var labelName = ((VssLabelAction)label.Action).Label;
                            if (string.IsNullOrEmpty(labelName))
                            {
                                logger.WriteLine("NOTE: Ignoring empty label");
                            }
                            else if (commitCount == 0)
                            {
                                logger.WriteLine("NOTE: Ignoring label '{0}' before initial commit", labelName);
                            }
                            else
                            {
                                var tagName = GetTagFromLabel(labelName);

                                var tagMessage = "Creating tag " + tagName;
                                if (tagName != labelName)
                                {
                                    tagMessage += " for label '" + labelName + "'";
                                }
                                LogStatus(work, tagMessage);

                                // tags always get a tag message;
                                var tagComment = label.Comment;
                                if (string.IsNullOrEmpty(tagComment))
                                {
                                    // use the original VSS label as the tag message if none was provided
                                    tagComment = labelName;
                                }

                                if (AbortRetryIgnore(
                                    delegate
                                    {
                                        vcsWrapper.Tag(tagName, label.User, GetEmail(label.User),
                                            tagComment, label.DateTime);
                                    }))
                                {
                                    ++tagCount;
                                }
                            }
                        }
                    }
                }

                stopwatch.Stop();

                if (!found)
                {
                    logger.WriteLine("Cannot Sync: VSS changeset at {0} not found.", continueAfter);
                    throw new ProcessException(string.Format("Cannot Sync: VSS changeset at {0} not found.", continueAfter), null, null);
                }

                logger.WriteSectionSeparator();
                logger.WriteLine(vcs + " export complete in {0:HH:mm:ss}", new DateTime(stopwatch.ElapsedTicks));
                logger.WriteLine("Replay time: {0:HH:mm:ss}", new DateTime(replayStopwatch.ElapsedTicks));
                logger.WriteLine(vcs + " time: {0:HH:mm:ss}", new DateTime(vcsWrapper.ElapsedTime().Ticks));
                logger.WriteLine(vcs + " commits: {0}", commitCount);
                logger.WriteLine(vcs + " tags: {0}", tagCount);
            });
        }
コード例 #15
0
ファイル: VcsExporter.cs プロジェクト: pokke123/vss2git
        private void SkipRevision(VssPathMapper pathMapper, Revision revision)
        {
            var actionType = revision.Action.Type;

            if (revision.Item.IsProject)
            {
                var project     = revision.Item;
                var projectPath = pathMapper.GetProjectPath(project.PhysicalName);

                VssItemName target      = null;
                string      targetPath  = null;
                var         namedAction = revision.Action as VssNamedAction;
                if (namedAction != null)
                {
                    target = namedAction.Name;
                    if (projectPath != null)
                    {
                        targetPath = Path.Combine(projectPath, target.LogicalName);
                    }
                }

                switch (actionType)
                {
                case VssActionType.Add:
                case VssActionType.Share:
                    pathMapper.AddItem(project, target);
                    break;

                case VssActionType.Recover:
                    pathMapper.RecoverItem(project, target);
                    break;

                case VssActionType.Delete:
                case VssActionType.Destroy:
                    pathMapper.DeleteItem(project, target);
                    break;

                case VssActionType.Rename:
                    pathMapper.RenameItem(target);
                    break;

                case VssActionType.MoveFrom:
                {
                    var moveFromAction = (VssMoveFromAction)revision.Action;
                    var isInside       = pathMapper.IsInRoot(moveFromAction.OriginalProject);

                    if (isInside)
                    {
                        pathMapper.MoveProjectFrom(project, target, moveFromAction.OriginalProject);
                    }
                    else
                    {
                        pathMapper.RecoverItem(project, target);
                    }
                }
                break;

                case VssActionType.MoveTo:
                {
                    var moveToAction = (VssMoveToAction)revision.Action;
                    var isInside     = pathMapper.IsInRoot(moveToAction.NewProject);
                    if (!isInside)
                    {
                        pathMapper.DeleteItem(project, target);
                    }
                }
                break;

                case VssActionType.Pin:
                {
                    var pinAction = (VssPinAction)revision.Action;
                    if (pinAction.Pinned)
                    {
                        pathMapper.PinItem(project, target);
                    }
                    else
                    {
                        pathMapper.UnpinItem(project, target);
                    }
                }
                break;

                case VssActionType.Branch:
                {
                    var branchAction = (VssBranchAction)revision.Action;
                    pathMapper.BranchFile(project, target, branchAction.Source);
                }
                break;

                case VssActionType.Restore:
                    pathMapper.AddItem(project, target);
                    break;
                }
            }
            // item is a file, not a project
            else if (actionType == VssActionType.Edit || actionType == VssActionType.Branch)
            {
                pathMapper.SetFileVersion(revision.Item, revision.Version);
            }
        }
コード例 #16
0
ファイル: GitExporter.cs プロジェクト: runt18/vss2git-1
        private bool ReplayRevision(VssPathMapper pathMapper, Revision revision,
            GitWrapper git, LinkedList<Revision> labels)
        {
            var needCommit = false;
            var actionType = revision.Action.Type;
            if (revision.Item.IsProject)
            {
                // note that project path (and therefore target path) can be
                // null if a project was moved and its original location was
                // subsequently destroyed
                var project = revision.Item;
                var projectName = project.LogicalName;
                var projectPath = pathMapper.GetProjectPath(project.PhysicalName);
                var projectDesc = projectPath;
                if (projectPath == null)
                {
                    projectDesc = revision.Item.ToString();
                    logger.WriteLine("NOTE: {0} is currently unmapped", project);
                }

                VssItemName target = null;
                string targetPath = null;
                var namedAction = revision.Action as VssNamedAction;
                if (namedAction != null)
                {
                    target = namedAction.Name;
                    if (projectPath != null)
                    {
                        targetPath = Path.Combine(projectPath, target.LogicalName);
                    }
                }

                bool isAddAction = false;
                bool writeProject = false;
                bool writeFile = false;
                VssItemInfo itemInfo = null;
                switch (actionType)
                {
                    case VssActionType.Label:
                        // defer tagging until after commit
                        labels.AddLast(revision);
                        break;

                    case VssActionType.Create:
                        // ignored; items are actually created when added to a project
                        break;

                    case VssActionType.Add:
                    case VssActionType.Share:
                        logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                        itemInfo = pathMapper.AddItem(project, target);
                        isAddAction = true;
                        break;

                    case VssActionType.Recover:
                        logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                        itemInfo = pathMapper.RecoverItem(project, target);
                        isAddAction = true;
                        break;

                    case VssActionType.Delete:
                    case VssActionType.Destroy:
                        {
                            logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                            itemInfo = pathMapper.DeleteItem(project, target);
                            if (targetPath != null && !itemInfo.Destroyed)
                            {
                                if (target.IsProject)
                                {
                                    if (Directory.Exists(targetPath))
                                    {
                                        if (((VssProjectInfo)itemInfo).ContainsFiles())
                                        {
                                            git.Remove(targetPath, true);
                                            needCommit = true;
                                        }
                                        else
                                        {
                                            // git doesn't care about directories with no files
                                            Directory.Delete(targetPath, true);
                                        }
                                    }
                                }
                                else
                                {
                                    if (File.Exists(targetPath))
                                    {
                                        // not sure how it can happen, but a project can evidently
                                        // contain another file with the same logical name, so check
                                        // that this is not the case before deleting the file
                                        if (pathMapper.ProjectContainsLogicalName(project, target))
                                        {
                                            logger.WriteLine("NOTE: {0} contains another file named {1}; not deleting file",
                                                projectDesc, target.LogicalName);
                                        }
                                        else
                                        {
                                            File.Delete(targetPath);
                                            needCommit = true;
                                        }
                                    }
                                }
                            }
                        }
                        break;

                    case VssActionType.Rename:
                        {
                            var renameAction = (VssRenameAction)revision.Action;
                            logger.WriteLine("{0}: {1} {2} to {3}",
                                projectDesc, actionType, renameAction.OriginalName, target.LogicalName);
                            itemInfo = pathMapper.RenameItem(target);
                            if (targetPath != null && !itemInfo.Destroyed)
                            {
                                var sourcePath = Path.Combine(projectPath, renameAction.OriginalName);
                                if (target.IsProject ? Directory.Exists(sourcePath) : File.Exists(sourcePath))
                                {
                                    // renaming a file or a project that contains files?
                                    var projectInfo = itemInfo as VssProjectInfo;
                                    if (projectInfo == null || projectInfo.ContainsFiles())
                                    {
                                        CaseSensitiveRename(sourcePath, targetPath, git.Move);
                                        needCommit = true;
                                    }
                                    else
                                    {
                                        // git doesn't care about directories with no files
                                        CaseSensitiveRename(sourcePath, targetPath, Directory.Move);
                                    }
                                }
                                else
                                {
                                    logger.WriteLine("NOTE: Skipping rename because {0} does not exist", sourcePath);
                                }
                            }
                        }
                        break;

                    case VssActionType.MoveFrom:
                        // if both MoveFrom & MoveTo are present (e.g.
                        // one of them has not been destroyed), only one
                        // can succeed, so check that the source exists
                        {
                            var moveFromAction = (VssMoveFromAction)revision.Action;
                            logger.WriteLine("{0}: Move from {1} to {2}",
                                projectDesc, moveFromAction.OriginalProject, targetPath ?? target.LogicalName);
                            var sourcePath = pathMapper.GetProjectPath(target.PhysicalName);
                            var projectInfo = pathMapper.MoveProjectFrom(
                                project, target, moveFromAction.OriginalProject);
                            if (targetPath != null && !projectInfo.Destroyed)
                            {
                                if (sourcePath != null && Directory.Exists(sourcePath))
                                {
                                    if (projectInfo.ContainsFiles())
                                    {
                                        git.Move(sourcePath, targetPath);
                                        needCommit = true;
                                    }
                                    else
                                    {
                                        // git doesn't care about directories with no files
                                        Directory.Move(sourcePath, targetPath);
                                    }
                                }
                                else
                                {
                                    // project was moved from a now-destroyed project
                                    writeProject = true;
                                }
                            }
                        }
                        break;

                    case VssActionType.MoveTo:
                        {
                            // handle actual moves in MoveFrom; this just does cleanup of destroyed projects
                            var moveToAction = (VssMoveToAction)revision.Action;
                            logger.WriteLine("{0}: Move to {1} from {2}",
                                projectDesc, moveToAction.NewProject, targetPath ?? target.LogicalName);
                            var projectInfo = pathMapper.MoveProjectTo(
                                project, target, moveToAction.NewProject);
                            if (projectInfo.Destroyed && targetPath != null && Directory.Exists(targetPath))
                            {
                                // project was moved to a now-destroyed project; remove empty directory
                                Directory.Delete(targetPath, true);
                            }
                        }
                        break;

                    case VssActionType.Pin:
                        {
                            var pinAction = (VssPinAction)revision.Action;
                            if (pinAction.Pinned)
                            {
                                logger.WriteLine("{0}: Pin {1}", projectDesc, target.LogicalName);
                                itemInfo = pathMapper.PinItem(project, target);
                            }
                            else
                            {
                                logger.WriteLine("{0}: Unpin {1}", projectDesc, target.LogicalName);
                                itemInfo = pathMapper.UnpinItem(project, target);
                                writeFile = !itemInfo.Destroyed;
                            }
                        }
                        break;

                    case VssActionType.Branch:
                        {
                            var branchAction = (VssBranchAction)revision.Action;
                            logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                            itemInfo = pathMapper.BranchFile(project, target, branchAction.Source);
                            // branching within the project might happen after branching of the file
                            writeFile = true;
                        }
                        break;

                    case VssActionType.Archive:
                        // currently ignored
                        {
                            var archiveAction = (VssArchiveAction)revision.Action;
                            logger.WriteLine("{0}: Archive {1} to {2} (ignored)",
                                projectDesc, target.LogicalName, archiveAction.ArchivePath);
                        }
                        break;

                    case VssActionType.Restore:
                        {
                            var restoreAction = (VssRestoreAction)revision.Action;
                            logger.WriteLine("{0}: Restore {1} from archive {2}",
                                projectDesc, target.LogicalName, restoreAction.ArchivePath);
                            itemInfo = pathMapper.AddItem(project, target);
                            isAddAction = true;
                        }
                        break;
                }

                if (targetPath != null)
                {
                    if (isAddAction)
                    {
                        if (revisionAnalyzer.IsDestroyed(target.PhysicalName) &&
                            !database.ItemExists(target.PhysicalName))
                        {
                            logger.WriteLine("NOTE: Skipping destroyed file: {0}", targetPath);
                            itemInfo.Destroyed = true;
                        }
                        else if (target.IsProject)
                        {
                            Directory.CreateDirectory(targetPath);
                            writeProject = true;
                        }
                        else
                        {
                            writeFile = true;
                        }
                    }

                    if (writeProject && pathMapper.IsProjectRooted(target.PhysicalName))
                    {
                        // create all contained subdirectories
                        foreach (var projectInfo in pathMapper.GetAllProjects(target.PhysicalName))
                        {
                            logger.WriteLine("{0}: Creating subdirectory {1}",
                                projectDesc, projectInfo.LogicalName);
                            Directory.CreateDirectory(projectInfo.GetPath());
                        }

                        // write current rev of all contained files
                        foreach (var fileInfo in pathMapper.GetAllFiles(target.PhysicalName))
                        {
                            if (WriteRevision(pathMapper, actionType, fileInfo.PhysicalName,
                                fileInfo.Version, target.PhysicalName, git))
                            {
                                // one or more files were written
                                needCommit = true;
                            }
                        }
                    }
                    else if (writeFile)
                    {
                        // write current rev to working path
                        int version = pathMapper.GetFileVersion(target.PhysicalName);
                        if (WriteRevisionTo(target.PhysicalName, version, targetPath))
                        {
                            // add file explicitly, so it is visible to subsequent git operations
                            git.Add(targetPath);
                            needCommit = true;
                        }
                    }
                }
            }
            // item is a file, not a project
            else if (actionType == VssActionType.Edit || actionType == VssActionType.Branch)
            {
                // if the action is Branch, the following code is necessary only if the item
                // was branched from a file that is not part of the migration subset; it will
                // make sure we start with the correct revision instead of the first revision

                var target = revision.Item;

                // update current rev
                pathMapper.SetFileVersion(target, revision.Version);

                // write current rev to all sharing projects
                WriteRevision(pathMapper, actionType, target.PhysicalName,
                    revision.Version, null, git);
                needCommit = true;
            }
            return needCommit;
        }
コード例 #17
0
        private bool ReplayRevision(VssPathMapper pathMapper, Revision revision,
                                    GitWrapper git, LinkedList <Revision> labels)
        {
            var needCommit = false;
            var actionType = revision.Action.Type;

            if (revision.Item.IsProject)
            {
                // note that project path (and therefore target path) can be
                // null if a project was moved and its original location was
                // subsequently destroyed
                var project     = revision.Item;
                var projectName = project.LogicalName;
                var projectPath = pathMapper.GetProjectPath(project.PhysicalName);
                var projectDesc = projectPath;
                if (projectPath == null)
                {
                    projectDesc = revision.Item.ToString();
                    logger.WriteLine("NOTE: {0} is currently unmapped", project);
                }

                VssItemName target      = null;
                string      targetPath  = null;
                var         namedAction = revision.Action as VssNamedAction;
                if (namedAction != null)
                {
                    target = namedAction.Name;
                    if (projectPath != null)
                    {
                        targetPath = Path.Combine(projectPath, target.LogicalName);
                    }
                }

                bool        isAddAction = false;
                bool        writeFile   = false;
                string      writeProjectPhysicalName = null;
                VssItemInfo itemInfo = null;
                switch (actionType)
                {
                case VssActionType.Label:
                    // defer tagging until after commit
                    labels.AddLast(revision);
                    break;

                case VssActionType.Create:
                    // ignored; items are actually created when added to a project
                    break;

                case VssActionType.Add:
                case VssActionType.Share:
                    logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                    itemInfo    = pathMapper.AddItem(project, target);
                    isAddAction = true;
                    break;

                case VssActionType.Recover:
                    logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                    itemInfo    = pathMapper.RecoverItem(project, target);
                    isAddAction = true;
                    break;

                case VssActionType.Delete:
                case VssActionType.Destroy:
                {
                    logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                    itemInfo = pathMapper.DeleteItem(project, target);
                    if (targetPath != null && !itemInfo.Destroyed)
                    {
                        if (target.IsProject)
                        {
                            if (Directory.Exists(targetPath))
                            {
                                string successor = pathMapper.TryToGetPhysicalNameContainedInProject(project, target);
                                if (successor != null)
                                {
                                    // we already have another project with the same logical name
                                    logger.WriteLine("NOTE: {0} contains another directory named {1}; not deleting directory",
                                                     projectDesc, target.LogicalName);
                                    writeProjectPhysicalName = successor;         // rewrite this project because it gets deleted below
                                }

                                if (((VssProjectInfo)itemInfo).ContainsFiles())
                                {
                                    git.Remove(targetPath, true);
                                    needCommit = true;
                                }
                                else
                                {
                                    // git doesn't care about directories with no files
                                    Directory.Delete(targetPath, true);
                                }
                            }
                        }
                        else
                        {
                            if (File.Exists(targetPath))
                            {
                                // not sure how it can happen, but a project can evidently
                                // contain another file with the same logical name, so check
                                // that this is not the case before deleting the file
                                if (pathMapper.TryToGetPhysicalNameContainedInProject(project, target) != null)
                                {
                                    logger.WriteLine("NOTE: {0} contains another file named {1}; not deleting file",
                                                     projectDesc, target.LogicalName);
                                }
                                else
                                {
                                    File.Delete(targetPath);
                                    needCommit = true;
                                }
                            }
                        }
                    }
                }
                break;

                case VssActionType.Rename:
                {
                    var renameAction = (VssRenameAction)revision.Action;
                    logger.WriteLine("{0}: {1} {2} to {3}",
                                     projectDesc, actionType, renameAction.OriginalName, target.LogicalName);
                    itemInfo = pathMapper.RenameItem(target);
                    if (targetPath != null && !itemInfo.Destroyed)
                    {
                        var sourcePath = Path.Combine(projectPath, renameAction.OriginalName);
                        if (target.IsProject ? Directory.Exists(sourcePath) : File.Exists(sourcePath))
                        {
                            // renaming a file or a project that contains files?
                            var projectInfo = itemInfo as VssProjectInfo;
                            if (projectInfo == null || projectInfo.ContainsFiles())
                            {
                                CaseSensitiveRename(sourcePath, targetPath, git.Move);
                                needCommit = true;
                            }
                            else
                            {
                                // git doesn't care about directories with no files
                                CaseSensitiveRename(sourcePath, targetPath, Directory.Move);
                            }
                        }
                        else
                        {
                            logger.WriteLine("NOTE: Skipping rename because {0} does not exist", sourcePath);
                        }
                    }
                }
                break;

                case VssActionType.MoveFrom:
                    // if both MoveFrom & MoveTo are present (e.g.
                    // one of them has not been destroyed), only one
                    // can succeed, so check that the source exists
                {
                    var moveFromAction = (VssMoveFromAction)revision.Action;
                    logger.WriteLine("{0}: Move from {1} to {2}",
                                     projectDesc, moveFromAction.OriginalProject, targetPath ?? target.LogicalName);
                    var sourcePath  = pathMapper.GetProjectPath(target.PhysicalName);
                    var projectInfo = pathMapper.MoveProjectFrom(
                        project, target, moveFromAction.OriginalProject);
                    if (targetPath != null && !projectInfo.Destroyed)
                    {
                        if (sourcePath != null && Directory.Exists(sourcePath))
                        {
                            if (projectInfo.ContainsFiles())
                            {
                                git.Move(sourcePath, targetPath);
                                needCommit = true;
                            }
                            else
                            {
                                // git doesn't care about directories with no files
                                Directory.Move(sourcePath, targetPath);
                            }
                        }
                        else
                        {
                            // project was moved from a now-destroyed project
                            writeProjectPhysicalName = target.PhysicalName;
                        }
                    }
                }
                break;

                case VssActionType.MoveTo:
                {
                    // handle actual moves in MoveFrom; this just does cleanup of destroyed projects
                    var moveToAction = (VssMoveToAction)revision.Action;
                    logger.WriteLine("{0}: Move to {1} from {2}",
                                     projectDesc, moveToAction.NewProject, targetPath ?? target.LogicalName);
                    var projectInfo = pathMapper.MoveProjectTo(
                        project, target, moveToAction.NewProject);
                    if (projectInfo.Destroyed && targetPath != null && Directory.Exists(targetPath))
                    {
                        // project was moved to a now-destroyed project; remove empty directory
                        Directory.Delete(targetPath, true);
                    }
                }
                break;

                case VssActionType.Pin:
                {
                    var pinAction = (VssPinAction)revision.Action;
                    if (pinAction.Pinned)
                    {
                        logger.WriteLine("{0}: Pin {1}", projectDesc, target.LogicalName);
                        itemInfo = pathMapper.PinItem(project, target);
                    }
                    else
                    {
                        logger.WriteLine("{0}: Unpin {1}", projectDesc, target.LogicalName);
                        itemInfo  = pathMapper.UnpinItem(project, target);
                        writeFile = !itemInfo.Destroyed;
                    }
                }
                break;

                case VssActionType.Branch:
                {
                    var branchAction = (VssBranchAction)revision.Action;
                    logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                    itemInfo = pathMapper.BranchFile(project, target, branchAction.Source);
                    // branching within the project might happen after branching of the file
                    writeFile = true;
                }
                break;

                case VssActionType.Archive:
                    // currently ignored
                {
                    var archiveAction = (VssArchiveAction)revision.Action;
                    logger.WriteLine("{0}: Archive {1} to {2} (ignored)",
                                     projectDesc, target.LogicalName, archiveAction.ArchivePath);
                }
                break;

                case VssActionType.Restore:
                {
                    var restoreAction = (VssRestoreAction)revision.Action;
                    logger.WriteLine("{0}: Restore {1} from archive {2}",
                                     projectDesc, target.LogicalName, restoreAction.ArchivePath);
                    itemInfo    = pathMapper.AddItem(project, target);
                    isAddAction = true;
                }
                break;
                }

                if (targetPath != null)
                {
                    if (isAddAction)
                    {
                        if (revisionAnalyzer.IsDestroyed(target.PhysicalName) &&
                            !database.ItemExists(target.PhysicalName))
                        {
                            logger.WriteLine("NOTE: Skipping destroyed file: {0}", targetPath);
                            itemInfo.Destroyed = true;
                        }
                        else if (target.IsProject)
                        {
                            Directory.CreateDirectory(targetPath);
                            writeProjectPhysicalName = target.PhysicalName;
                        }
                        else
                        {
                            writeFile = true;
                        }
                    }

                    if (writeProjectPhysicalName != null && pathMapper.IsProjectRooted(writeProjectPhysicalName))
                    {
                        // create all contained subdirectories
                        foreach (var projectInfo in pathMapper.GetAllProjects(writeProjectPhysicalName))
                        {
                            logger.WriteLine("{0}: Creating subdirectory {1}",
                                             projectDesc, projectInfo.LogicalName);
                            Directory.CreateDirectory(projectInfo.GetPath());
                        }

                        // write current rev of all contained files
                        foreach (var fileInfo in pathMapper.GetAllFiles(writeProjectPhysicalName))
                        {
                            if (WriteRevision(pathMapper, actionType, fileInfo.PhysicalName,
                                              fileInfo.Version, writeProjectPhysicalName, git))
                            {
                                // one or more files were written
                                needCommit = true;
                            }
                        }
                    }
                    else if (writeFile)
                    {
                        // write current rev to working path
                        int version = pathMapper.GetFileVersion(target.PhysicalName);
                        if (WriteRevisionTo(target.PhysicalName, version, targetPath))
                        {
                            // add file explicitly, so it is visible to subsequent git operations
                            git.Add(targetPath);
                            needCommit = true;
                        }
                    }
                }
            }
            // item is a file, not a project
            else if (actionType == VssActionType.Edit || actionType == VssActionType.Branch)
            {
                // if the action is Branch, the following code is necessary only if the item
                // was branched from a file that is not part of the migration subset; it will
                // make sure we start with the correct revision instead of the first revision

                var target = revision.Item;

                // update current rev
                pathMapper.SetFileVersion(target, revision.Version);

                // write current rev to all sharing projects
                WriteRevision(pathMapper, actionType, target.PhysicalName,
                              revision.Version, null, git);
                needCommit = true;
            }
            return(needCommit);
        }
コード例 #18
0
ファイル: GitExporter.cs プロジェクト: runt18/vss2git-1
 private bool WriteRevision(VssPathMapper pathMapper, VssActionType actionType,
     string physicalName, int version, string underProject, GitWrapper git)
 {
     var needCommit = false;
     var paths = pathMapper.GetFilePaths(physicalName, underProject);
     foreach (string path in paths)
     {
         logger.WriteLine("{0}: {1} revision {2}", path, actionType, version);
         if (WriteRevisionTo(physicalName, version, path))
         {
             // add file explicitly, so it is visible to subsequent git operations
             git.Add(path);
             needCommit = true;
         }
     }
     return needCommit;
 }
コード例 #19
0
        public void ExportToGit(string repoPath)
        {
            workQueue.AddLast(delegate(object work)
            {
                var stopwatch = Stopwatch.StartNew();

                logger.WriteSectionSeparator();
                LogStatus(work, "Initializing Git repository");

                // create repository directory if it does not exist
                if (!Directory.Exists(repoPath))
                {
                    Directory.CreateDirectory(repoPath);
                }

                var git            = new GitWrapper(repoPath, logger);
                git.CommitEncoding = commitEncoding;

                while (!git.FindExecutable())
                {
                    var button = MessageBox.Show("Git not found in PATH. " +
                                                 "If you need to modify your PATH variable, please " +
                                                 "restart the program for the changes to take effect.",
                                                 "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                    if (button == DialogResult.Cancel)
                    {
                        workQueue.Abort();
                        return;
                    }
                }

                if (!RetryCancel(delegate { git.Init(); }))
                {
                    return;
                }

                if (commitEncoding.WebName != "utf-8")
                {
                    AbortRetryIgnore(delegate
                    {
                        git.SetConfig("i18n.commitencoding", commitEncoding.WebName);
                    });
                }

                var pathMapper = new VssPathMapper();

                // create mappings for root projects
                foreach (var rootProject in revisionAnalyzer.RootProjects)
                {
                    var rootPath = VssPathMapper.GetWorkingPath(repoPath, rootProject.Path);
                    pathMapper.SetProjectPath(rootProject.PhysicalName, rootPath, rootProject.Path);
                }

                // replay each changeset
                var changesetId     = 1;
                var changesets      = changesetBuilder.Changesets;
                var commitCount     = 0;
                var tagCount        = 0;
                var replayStopwatch = new Stopwatch();
                var labels          = new LinkedList <Revision>();
                tagsUsed.Clear();
                foreach (var changeset in changesets)
                {
                    var changesetDesc = string.Format(CultureInfo.InvariantCulture,
                                                      "changeset {0} from {1}", changesetId, changeset.DateTime);

                    // replay each revision in changeset
                    LogStatus(work, "Replaying " + changesetDesc);
                    labels.Clear();
                    replayStopwatch.Start();
                    bool needCommit;
                    try
                    {
                        needCommit = ReplayChangeset(pathMapper, changeset, git, labels);
                    }
                    finally
                    {
                        replayStopwatch.Stop();
                    }

                    if (workQueue.IsAborting)
                    {
                        return;
                    }

                    // commit changes
                    if (needCommit)
                    {
                        LogStatus(work, "Committing " + changesetDesc);
                        if (CommitChangeset(git, changeset))
                        {
                            ++commitCount;
                        }
                    }

                    if (workQueue.IsAborting)
                    {
                        return;
                    }

                    // create tags for any labels in the changeset
                    if (labels.Count > 0)
                    {
                        foreach (Revision label in labels)
                        {
                            var labelName = ((VssLabelAction)label.Action).Label;
                            if (string.IsNullOrEmpty(labelName))
                            {
                                logger.WriteLine("NOTE: Ignoring empty label");
                            }
                            else if (commitCount == 0)
                            {
                                logger.WriteLine("NOTE: Ignoring label '{0}' before initial commit", labelName);
                            }
                            else
                            {
                                var tagName = GetTagFromLabel(labelName);

                                var tagMessage = "Creating tag " + tagName;
                                if (tagName != labelName)
                                {
                                    tagMessage += " for label '" + labelName + "'";
                                }
                                LogStatus(work, tagMessage);

                                // annotated tags require (and are implied by) a tag message;
                                // tools like Mercurial's git converter only import annotated tags
                                var tagComment = label.Comment;
                                if (string.IsNullOrEmpty(tagComment) && forceAnnotatedTags)
                                {
                                    // use the original VSS label as the tag message if none was provided
                                    tagComment = labelName;
                                }

                                if (AbortRetryIgnore(
                                        delegate
                                {
                                    git.Tag(tagName, label.User, GetEmail(label.User),
                                            tagComment, label.DateTime);
                                }))
                                {
                                    ++tagCount;
                                }
                            }
                        }
                    }

                    ++changesetId;
                }

                stopwatch.Stop();

                logger.WriteSectionSeparator();
                logger.WriteLine("Git export complete in {0:HH:mm:ss}", new DateTime(stopwatch.ElapsedTicks));
                logger.WriteLine("Replay time: {0:HH:mm:ss}", new DateTime(replayStopwatch.ElapsedTicks));
                logger.WriteLine("Git time: {0:HH:mm:ss}", new DateTime(git.ElapsedTime.Ticks));
                logger.WriteLine("Git commits: {0}", commitCount);
                logger.WriteLine("Git tags: {0}", tagCount);
            });
        }
コード例 #20
0
        private bool ReplayRevision(VssPathMapper pathMapper, Revision revision,
                                    GitWrapper git, LinkedList <Revision> labels)
        {
            var needCommit = false;
            var actionType = revision.Action.Type;

            if (revision.Item.IsProject)
            {
                // note that project path (and therefore target path) can be
                // null if a project was moved and its original location was
                // subsequently destroyed
                var project     = revision.Item;
                var projectPath = pathMapper.GetProjectPath(project.PhysicalName);
                var projectDesc = projectPath;
                if (projectPath == null)
                {
                    projectDesc = revision.Item.ToString();
                    logger.WriteLine("NOTE: {0} is currently unmapped", project);
                }

                VssItemName target     = null;
                string      targetPath = null;
                if (revision.Action is VssNamedAction namedAction)
                {
                    target = namedAction.Name;
                    if (projectPath != null)
                    {
                        targetPath = Path.Combine(projectPath, target.LogicalName);
                    }
                }

                var         isAddAction  = false;
                var         writeProject = false;
                var         writeFile    = false;
                VssItemInfo itemInfo     = null;
                switch (actionType)
                {
                case VssActionType.Label:
                    // defer tagging until after commit
                    labels.AddLast(revision);
                    break;

                case VssActionType.Create:
                    // ignored; items are actually created when added to a project
                    break;

                case VssActionType.Add:
                case VssActionType.Share:
                    logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                    itemInfo    = pathMapper.AddItem(project, target);
                    isAddAction = true;
                    break;

                case VssActionType.Recover:
                    logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                    itemInfo    = pathMapper.RecoverItem(project, target);
                    isAddAction = true;
                    break;

                case VssActionType.Delete:
                case VssActionType.Destroy:
                {
                    logger.WriteLine("{0}: {1} {2}", projectDesc, actionType, target.LogicalName);
                    itemInfo = pathMapper.DeleteItem(project, target);
                    if (targetPath != null && !itemInfo.Destroyed)
                    {
                        if (target.IsProject)
                        {
                            if (Directory.Exists(targetPath))
                            {
                                if (((VssProjectInfo)itemInfo).ContainsFiles())
                                {
                                    git.Remove(targetPath, true);
                                    needCommit = true;
                                }
                                else
                                {
                                    // git doesn't care about directories with no files
                                    Directory.Delete(targetPath, true);
                                }
                            }
                        }
                        else
                        {
                            if (File.Exists(targetPath))
                            {
                                // not sure how it can happen, but a project can evidently
                                // contain another file with the same logical name, so check
                                // that this is not the case before deleting the file
                                if (pathMapper.ProjectContainsLogicalName(project, target))
                                {
                                    logger.WriteLine("NOTE: {0} contains another file named {1}; not deleting file",
                                                     projectDesc, target.LogicalName);
                                }
                                else
                                {
                                    File.Delete(targetPath);
                                    needCommit = true;
                                }
                            }
                        }
                    }
                }
                break;

                case VssActionType.Rename:
                {
                    var renameAction = (VssRenameAction)revision.Action;
                    logger.WriteLine("{0}: {1} {2} to {3}",
                                     projectDesc, actionType, renameAction.OriginalName, target.LogicalName);
                    itemInfo = pathMapper.RenameItem(target);
                    if (targetPath != null && !itemInfo.Destroyed)
                    {
                        var sourcePath = Path.Combine(projectPath, renameAction.OriginalName);
                        if (target.IsProject ? Directory.Exists(sourcePath) : File.Exists(sourcePath))
                        {
                            // renaming a file or a project that contains files?
                            if (!(itemInfo is VssProjectInfo projectInfo) || (projectInfo.ContainsFiles() && projectInfo.Items.All(x => !x.Destroyed)))
                            {
                                CaseSensitiveRename(sourcePath, targetPath, git.Move);
                                needCommit = true;
                            }
                            else
                            {
                                // git doesn't care about directories with no files
                                CaseSensitiveRename(sourcePath, targetPath, CaseSensitiveDirectoryMove);
                            }
                        }
                        else
                        {
                            logger.WriteLine("NOTE: Skipping rename because {0} does not exist", sourcePath);
                        }
                    }
                }
                break;