Fetch all the merge changesets and interdependant branches when clone --with-branches
This commit is contained in:
@@ -59,14 +59,13 @@ namespace Sep.Git.Tfs.Commands
|
||||
var retVal = init.Run(tfsUrl, tfsRepositoryPath, gitRepositoryPath);
|
||||
|
||||
VerifyTfsPathToClone(tfsRepositoryPath);
|
||||
|
||||
if (retVal == 0) retVal = fetch.Run();
|
||||
if (retVal == 0) globals.Repository.CommandNoisy("merge", globals.Repository.ReadTfsRemote(globals.RemoteId).RemoteRef);
|
||||
if (retVal == 0 && withBranches && initBranch != null)
|
||||
if (retVal == 0) fetch.Run(withBranches);
|
||||
if (withBranches && initBranch != null)
|
||||
{
|
||||
initBranch.CloneAllBranches = true;
|
||||
retVal = initBranch.Run();
|
||||
}
|
||||
globals.Repository.CommandNoisy("merge", globals.Repository.ReadTfsRemote(globals.RemoteId).RemoteRef);
|
||||
return retVal;
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -61,24 +61,42 @@ namespace Sep.Git.Tfs.Commands
|
||||
return Run(globals.RemoteId);
|
||||
}
|
||||
|
||||
public void Run(bool stopOnFailMergeCommit)
|
||||
{
|
||||
authors.Parse(AuthorsFilePath, globals.GitDir);
|
||||
|
||||
var remote = GetRemotesToFetch(new List<string>{globals.RemoteId}).First();
|
||||
FetchRemote(stopOnFailMergeCommit, remote);
|
||||
}
|
||||
|
||||
public int Run(params string[] args)
|
||||
{
|
||||
return Run(false, args);
|
||||
}
|
||||
|
||||
private int Run(bool stopOnFailMergeCommit, params string[] args)
|
||||
{
|
||||
authors.Parse(AuthorsFilePath, globals.GitDir);
|
||||
|
||||
foreach (var remote in GetRemotesToFetch(args))
|
||||
{
|
||||
FetchRemote(stopOnFailMergeCommit, remote);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void FetchRemote(bool stopOnFailMergeCommit, IGitTfsRemote remote)
|
||||
{
|
||||
Trace.WriteLine("Fetching from TFS remote " + remote.Id);
|
||||
DoFetch(remote);
|
||||
DoFetch(remote, stopOnFailMergeCommit);
|
||||
if (labels != null && FetchLabels)
|
||||
{
|
||||
Trace.WriteLine("Fetching labels from TFS remote " + remote.Id);
|
||||
labels.Run(remote);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected virtual void DoFetch(IGitTfsRemote remote)
|
||||
protected virtual void DoFetch(IGitTfsRemote remote, bool stopOnFailMergeCommit)
|
||||
{
|
||||
// It is possible that we have outdated refs/remotes/tfs/<id>.
|
||||
// E.g. someone already fetched changesets from TFS into another git repository and we've pulled it since
|
||||
@@ -86,7 +104,7 @@ namespace Sep.Git.Tfs.Commands
|
||||
// TFS exists (by checking git-tfs-id mark in commit's comments).
|
||||
// The process is similar to bootstrapping.
|
||||
globals.Repository.MoveTfsRefForwardIfNeeded(remote);
|
||||
remote.Fetch();
|
||||
remote.Fetch(stopOnFailMergeCommit);
|
||||
|
||||
Trace.WriteLine("Cleaning...");
|
||||
remote.CleanupWorkspaceDirectory();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
@@ -66,6 +67,12 @@ namespace Sep.Git.Tfs.Commands
|
||||
var allRemotes = _globals.Repository.ReadAllTfsRemotes();
|
||||
|
||||
tfsBranchPath.AssertValidTfsPath();
|
||||
if (allRemotes.Count(r => r.TfsRepositoryPath.ToLower() == tfsBranchPath.ToLower()) != 0)
|
||||
{
|
||||
_stdout.WriteLine("warning : There is already a remote for this tfs branch. Branch ignored!");
|
||||
return GitTfsExitCodes.InvalidArguments;
|
||||
}
|
||||
|
||||
int rootChangeSetId;
|
||||
if (ParentBranch == null)
|
||||
rootChangeSetId = defaultRemote.Tfs.GetRootChangesetForBranch(tfsBranchPath);
|
||||
@@ -78,7 +85,26 @@ namespace Sep.Git.Tfs.Commands
|
||||
rootChangeSetId = defaultRemote.Tfs.GetRootChangesetForBranch(tfsBranchPath, tfsRepositoryPathParentBranchFound.TfsRepositoryPath);
|
||||
}
|
||||
|
||||
return CreateBranch(defaultRemote, tfsBranchPath, rootChangeSetId, allRemotes, gitBranchNameExpected);
|
||||
var sha1RootCommit = FindChangesetInGitRepository(rootChangeSetId);
|
||||
if (string.IsNullOrWhiteSpace(sha1RootCommit))
|
||||
throw new GitTfsException("error: The root changeset " + rootChangeSetId +
|
||||
" have not be found in the Git repository. The branch containing the changeset should not have been created. Please do it before retrying!!\n");
|
||||
var tfsRemote = CreateBranch(defaultRemote, tfsBranchPath, sha1RootCommit, gitBranchNameExpected);
|
||||
if (tfsRemote != null)
|
||||
{
|
||||
FetchRemote(tfsRemote, false);
|
||||
return GitTfsExitCodes.OK;
|
||||
}
|
||||
|
||||
return GitTfsExitCodes.ExceptionThrown;
|
||||
}
|
||||
|
||||
class BranchDatas
|
||||
{
|
||||
public string TfsRepositoryPath { get; set; }
|
||||
public IGitTfsRemote TfsRemote { get; set; }
|
||||
public bool IsEntirelyFetched { get; set; }
|
||||
public long RootChangesetId { get; set; }
|
||||
}
|
||||
|
||||
public int Run()
|
||||
@@ -91,32 +117,47 @@ namespace Sep.Git.Tfs.Commands
|
||||
|
||||
var defaultRemote = InitFromDefaultRemote();
|
||||
|
||||
var allRemotes = _globals.Repository.ReadAllTfsRemotes();
|
||||
|
||||
var rootBranch = defaultRemote.Tfs.GetRootTfsBranchForRemotePath(defaultRemote.TfsRepositoryPath);
|
||||
if (rootBranch == null)
|
||||
throw new GitTfsException(string.Format("error: Init all the branches is only possible when 'git tfs clone' was done from the trunk!!! '{0}' is not a TFS branch!", defaultRemote.TfsRepositoryPath));
|
||||
if (defaultRemote.TfsRepositoryPath.ToLower() != rootBranch.Path.ToLower())
|
||||
throw new GitTfsException(string.Format("error: Init all the branches is only possible when 'git tfs clone' was done from the trunk!!! Please clone again from '{0}'...", rootBranch.Path));
|
||||
|
||||
var childBranchPaths = rootBranch.GetAllChildren().Select(b=>b.Path).ToList();
|
||||
var childBranchPaths = rootBranch.GetAllChildren().Select(b=>new BranchDatas{TfsRepositoryPath = b.Path}).ToList();
|
||||
|
||||
_stdout.WriteLine("Tfs branches found:");
|
||||
foreach (var tfsBranchPath in childBranchPaths)
|
||||
for (int iBranch = 0; iBranch < childBranchPaths.Count; iBranch++)
|
||||
{
|
||||
_stdout.WriteLine("- " + tfsBranchPath);
|
||||
var tfsBranch = childBranchPaths[iBranch];
|
||||
_stdout.WriteLine("- " + tfsBranch.TfsRepositoryPath);
|
||||
tfsBranch.RootChangesetId = defaultRemote.Tfs.GetRootChangesetForBranch(tfsBranch.TfsRepositoryPath);
|
||||
}
|
||||
childBranchPaths.Add(new BranchDatas{TfsRepositoryPath = defaultRemote.TfsRepositoryPath, TfsRemote = defaultRemote, RootChangesetId = -1});
|
||||
|
||||
foreach (var tfsBranchPath in childBranchPaths)
|
||||
do
|
||||
{
|
||||
var rootChangeSetId = defaultRemote.Tfs.GetRootChangesetForBranch(tfsBranchPath);
|
||||
var result = CreateBranch(defaultRemote, tfsBranchPath, rootChangeSetId, allRemotes);
|
||||
if (result < 0)
|
||||
return result;
|
||||
var branchesToFetch = childBranchPaths.Where(b => !b.IsEntirelyFetched).ToList();
|
||||
foreach (var tfsBranch in branchesToFetch)
|
||||
{
|
||||
Trace.WriteLine("=> Working on TFS branch : " + tfsBranch.TfsRepositoryPath);
|
||||
if (tfsBranch.TfsRemote == null)
|
||||
{
|
||||
var sha1RootCommit = FindChangesetInGitRepository(tfsBranch.RootChangesetId);
|
||||
if (sha1RootCommit != null)
|
||||
tfsBranch.TfsRemote = CreateBranch(defaultRemote, tfsBranch.TfsRepositoryPath, sha1RootCommit);
|
||||
}
|
||||
if (tfsBranch.TfsRemote != null)
|
||||
{
|
||||
Trace.WriteLine("Fetching remote :" + tfsBranch.TfsRemote.Id);
|
||||
var fr = FetchRemote(tfsBranch.TfsRemote, true);
|
||||
tfsBranch.IsEntirelyFetched = fr.IsSuccess;
|
||||
}
|
||||
}
|
||||
} while (childBranchPaths.Any(b => !b.IsEntirelyFetched));
|
||||
return GitTfsExitCodes.OK;
|
||||
}
|
||||
|
||||
|
||||
private IGitTfsRemote InitFromDefaultRemote()
|
||||
{
|
||||
var defaultRemote = _globals.Repository.ReadTfsRemote(GitTfsConstants.DefaultRepositoryId);
|
||||
@@ -140,59 +181,69 @@ namespace Sep.Git.Tfs.Commands
|
||||
return defaultRemote;
|
||||
}
|
||||
|
||||
private int CreateBranch(IGitTfsRemote defaultRemote, string tfsRepositoryPath, int rootChangeSetId, IEnumerable<IGitTfsRemote> allRemotes, string gitBranchNameExpected = null)
|
||||
private IGitTfsRemote CreateBranch(IGitTfsRemote defaultRemote, string tfsRepositoryPath, string sha1RootCommit, string gitBranchNameExpected = null)
|
||||
{
|
||||
Trace.WriteLine("=> Working on TFS branch : " + tfsRepositoryPath);
|
||||
if (rootChangeSetId == -1)
|
||||
throw new GitTfsException("error: No root changeset found :( \n");
|
||||
|
||||
Trace.WriteLine("Begin process of creating branch for remote :" + tfsRepositoryPath);
|
||||
// TFS string representations of repository paths do not end in trailing slashes
|
||||
tfsRepositoryPath = (tfsRepositoryPath ?? string.Empty).TrimEnd('/');
|
||||
|
||||
if (allRemotes.Count(r => r.TfsRepositoryPath.ToLower() == tfsRepositoryPath.ToLower()) != 0)
|
||||
{
|
||||
Trace.WriteLine("There is already a remote for this tfs branch. Branch ignored!");
|
||||
return GitTfsExitCodes.InvalidArguments;
|
||||
}
|
||||
|
||||
string gitBranchName;
|
||||
if (!string.IsNullOrWhiteSpace(gitBranchNameExpected))
|
||||
gitBranchName = ExtractGitBranchNameFromTfsRepositoryPath(gitBranchNameExpected);
|
||||
else
|
||||
gitBranchName = ExtractGitBranchNameFromTfsRepositoryPath(tfsRepositoryPath);
|
||||
if(string.IsNullOrWhiteSpace(gitBranchName))
|
||||
if (string.IsNullOrWhiteSpace(gitBranchName))
|
||||
throw new GitTfsException("error: The Git branch name '" + gitBranchName + "' is not valid...\n");
|
||||
Trace.WriteLine("Git local branch will be :" + gitBranchName);
|
||||
|
||||
Trace.WriteLine("Found root changeset : " + rootChangeSetId);
|
||||
|
||||
Trace.WriteLine("Try to find changeset in git repository...");
|
||||
string sha1RootCommit = _globals.Repository.FindCommitHashByCommitMessage("git-tfs-id: .*;C" + rootChangeSetId + "[^0-9]");
|
||||
//sha1RootCommit = _globals.Repository.FindCommitByCommitMessage("git-tfs-id: .*\\$\\/" + tfsProject + "\\/.*;C" + rootChangeSetId + "[^0-9]");
|
||||
if (string.IsNullOrWhiteSpace(sha1RootCommit))
|
||||
throw new GitTfsException("error: The root changeset " + rootChangeSetId + " have not be found in the Git repository. The branch containing the changeset should not have been created. Please do it before retrying!!\n");
|
||||
Trace.WriteLine("Commit found! sha1 : " + sha1RootCommit);
|
||||
|
||||
Trace.WriteLine("Try creating remote...");
|
||||
var tfsRemote = _globals.Repository.CreateTfsRemote(new RemoteInfo { Id = gitBranchName, Url = defaultRemote.TfsUrl, Repository = tfsRepositoryPath, RemoteOptions = _remoteOptions });
|
||||
var tfsRemote = _globals.Repository.CreateTfsRemote(new RemoteInfo
|
||||
{
|
||||
Id = gitBranchName,
|
||||
Url = defaultRemote.TfsUrl,
|
||||
Repository = tfsRepositoryPath,
|
||||
RemoteOptions = _remoteOptions
|
||||
});
|
||||
if (!_globals.Repository.CreateBranch(tfsRemote.RemoteRef, sha1RootCommit))
|
||||
throw new GitTfsException("error: Fail to create remote branch ref file!");
|
||||
Trace.WriteLine("Remote created!");
|
||||
return tfsRemote;
|
||||
}
|
||||
|
||||
private string FindChangesetInGitRepository(long rootChangeSetId)
|
||||
{
|
||||
if (rootChangeSetId == -1)
|
||||
throw new GitTfsException("error: No root changeset found :( \n");
|
||||
Trace.WriteLine("Found root changeset : " + rootChangeSetId);
|
||||
Trace.WriteLine("Try to find changeset " + rootChangeSetId + " in git repository...");
|
||||
string sha1RootCommit = _globals.Repository.FindCommitHashByCommitMessage("git-tfs-id: .*;C" + rootChangeSetId + "[^0-9]");
|
||||
//sha1RootCommit = _globals.Repository.FindCommitByCommitMessage("git-tfs-id: .*\\$\\/" + tfsProject + "\\/.*;C" + rootChangeSetId + "[^0-9]");
|
||||
if (sha1RootCommit != null)
|
||||
Trace.WriteLine("Commit found! sha1 : " + sha1RootCommit);
|
||||
else
|
||||
Trace.WriteLine("Commit not found!");
|
||||
return sha1RootCommit;
|
||||
}
|
||||
|
||||
private IFetchResult FetchRemote(IGitTfsRemote tfsRemote, bool stopOnFailMergeCommit)
|
||||
{
|
||||
Trace.WriteLine("Try fetching changesets...");
|
||||
tfsRemote.Fetch();
|
||||
var fr = tfsRemote.Fetch(stopOnFailMergeCommit);
|
||||
Trace.WriteLine("Changesets fetched!");
|
||||
|
||||
if (fr.IsSuccess && tfsRemote.Id != GitTfsConstants.DefaultRepositoryId)
|
||||
{
|
||||
Trace.WriteLine("Try creating the local branch...");
|
||||
if (!_globals.Repository.CreateBranch("refs/heads/" + gitBranchName, tfsRemote.MaxCommitHash))
|
||||
if (!_globals.Repository.CreateBranch("refs/heads/" + tfsRemote.Id, tfsRemote.MaxCommitHash))
|
||||
_stdout.WriteLine("warning: Fail to create local branch ref file!");
|
||||
else
|
||||
Trace.WriteLine("Local branch created!");
|
||||
}
|
||||
|
||||
Trace.WriteLine("Cleaning...");
|
||||
tfsRemote.CleanupWorkspaceDirectory();
|
||||
|
||||
return GitTfsExitCodes.OK;
|
||||
return fr;
|
||||
}
|
||||
|
||||
protected string ExtractGitBranchNameFromTfsRepositoryPath(string tfsRepositoryPath)
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Sep.Git.Tfs.Commands
|
||||
|
||||
private int? InitialChangeset { get; set; }
|
||||
|
||||
protected override void DoFetch(IGitTfsRemote remote)
|
||||
protected override void DoFetch(IGitTfsRemote remote, bool stopOnFailMergeCommit)
|
||||
{
|
||||
if (InitialChangeset.HasValue)
|
||||
remote.QuickFetch(InitialChangeset.Value);
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace Sep.Git.Tfs.Commands
|
||||
try
|
||||
{
|
||||
newChangesetId = tfsRemote.Checkin(target, currentParent, parentChangeset, commitSpecificCheckinOptions, tfsRepositoryPathOfMergedBranch);
|
||||
tfsRemote.FetchWithMerge(newChangesetId, rc.Parents);
|
||||
tfsRemote.FetchWithMerge(newChangesetId, false, rc.Parents);
|
||||
if (tfsRemote.MaxChangesetId != newChangesetId)
|
||||
{
|
||||
var lastCommit = repo.FindCommitHashByCommitMessage("git-tfs-id: .*;C" + newChangesetId + "[^0-9]");
|
||||
@@ -130,7 +130,7 @@ namespace Sep.Git.Tfs.Commands
|
||||
}
|
||||
|
||||
currentParent = target;
|
||||
parentChangeset = new TfsChangesetInfo { ChangesetId = newChangesetId, GitCommit = tfsRemote.MaxCommitHash, Remote = tfsRemote };
|
||||
parentChangeset = new TfsChangesetInfo {ChangesetId = newChangesetId, GitCommit = tfsRemote.MaxCommitHash, Remote = tfsRemote};
|
||||
_stdout.WriteLine("Done with {0}.", target);
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -184,12 +184,12 @@ namespace Sep.Git.Tfs.Commands
|
||||
|
||||
_stdout.WriteLine("Starting checkin of {0} '{1}'", target.Substring(0, 8), commitSpecificCheckinOptions.CheckinComment);
|
||||
long newChangesetId = tfsRemote.Checkin(rc.Sha, parentChangeset, commitSpecificCheckinOptions, tfsRepositoryPathOfMergedBranch);
|
||||
tfsRemote.FetchWithMerge(newChangesetId, rc.Parents);
|
||||
tfsRemote.FetchWithMerge(newChangesetId, false, rc.Parents);
|
||||
if (tfsRemote.MaxChangesetId != newChangesetId)
|
||||
throw new GitTfsException("error: New TFS changesets were found. Rcheckin was not finished.");
|
||||
|
||||
tfsLatest = tfsRemote.MaxCommitHash;
|
||||
parentChangeset = new TfsChangesetInfo { ChangesetId = newChangesetId, GitCommit = tfsLatest, Remote = tfsRemote };
|
||||
parentChangeset = new TfsChangesetInfo {ChangesetId = newChangesetId, GitCommit = tfsLatest, Remote = tfsRemote};
|
||||
_stdout.WriteLine("Done with {0}, rebasing tail onto new TFS-commit...", target);
|
||||
|
||||
RebaseOnto(repo, tfsLatest, target);
|
||||
|
||||
+10
-10
@@ -219,17 +219,17 @@ namespace Sep.Git.Tfs.Core
|
||||
log.CommitParents.Add(shaParent);
|
||||
else
|
||||
{
|
||||
if (stopOnFailMergeCommit)
|
||||
{
|
||||
fr.IsSuccess = false;
|
||||
fr.LastFetchedChangesetId = MaxChangesetId;
|
||||
return fr;
|
||||
}
|
||||
//TODO : Manage case where there is not yet a git commit for the parent changset!!!!!
|
||||
if (stopOnFailMergeCommit)
|
||||
{
|
||||
fr.IsSuccess = false;
|
||||
fr.LastFetchedChangesetId = MaxChangesetId;
|
||||
return fr;
|
||||
}
|
||||
//TODO : Manage case where there is not yet a git commit for the parent changset!!!!!
|
||||
stdout.WriteLine("warning: found merge changeset "+ changeset.Summary.ChangesetId +" but unable to manage it due to lack of local commit for changeset " + parentChangesetId +
|
||||
"! Fetch the corresponding branch before...");
|
||||
}
|
||||
}
|
||||
"! Fetch the corresponding branch before...");
|
||||
}
|
||||
}
|
||||
if (changeset.Summary.ChangesetId == mergeChangesetId)
|
||||
{
|
||||
foreach (var parent in parentCommitsHashes)
|
||||
|
||||
Reference in New Issue
Block a user