Skip to content

Commit

Permalink
Completed the unshelve spike.
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Burke authored and ivan-danilov committed Aug 3, 2011
1 parent ed1c171 commit 37fb702
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 12 deletions.
178 changes: 171 additions & 7 deletions GitTfs.VsCommon/TfsHelper.Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Sep.Git.Tfs.Core;
using Sep.Git.Tfs.Core.TfsInterop;
using StructureMap;
using ChangeType = Microsoft.TeamFoundation.Server.ChangeType;

namespace Sep.Git.Tfs.VsCommon
{
Expand Down Expand Up @@ -183,20 +184,183 @@ public bool HasShelveset(string shelvesetName)

public abstract bool CanShowCheckinDialog { get; }

public void Unshelve(Sep.Git.Tfs.Commands.Unshelve unshelve, IList<string> args)
[Obsolete("TODO: un-spike-ify this.")]
public int Unshelve(Sep.Git.Tfs.Commands.Unshelve unshelve, IGitTfsRemote remote, IList<string> args)
{
var ListShelvesets = new Action<Shelveset[]>(shelvesets =>
{
foreach (var shelveset in shelvesets)
{
_stdout.WriteLine(" {0,-20} {1,-20}",
shelveset.OwnerName,
shelveset.Name);
}
});
var shelvesetOwner = unshelve.Owner == "all" ? null : (unshelve.Owner ?? VersionControl.AuthenticatedUser);
if(unshelve.List)
{
var user = unshelve.Owner == "all" ? null : (unshelve.Owner ?? VersionControl.AuthenticatedUser);
var shelvesets = VersionControl.QueryShelvesets(null, user);
foreach(var shelveset in shelvesets)
var shelvesets = VersionControl.QueryShelvesets(null, shelvesetOwner);
ListShelvesets(shelvesets);
}
else
{
if(args.Count != 2)
{
_stdout.WriteLine("ERROR: Two arguments are required.");
return GitTfsExitCodes.InvalidArguments;
}
var shelvesetName = args[0];
var destinationBranch = args[1];

var shelvesets = VersionControl.QueryShelvesets(shelvesetName, shelvesetOwner);
if(shelvesets.Length != 1)
{
_stdout.WriteLine("ERROR: Unable to find shelveset \"" + shelvesetName + "\" (" + shelvesets.Length + " matches).");
ListShelvesets(shelvesets);
return GitTfsExitCodes.InvalidArguments;
}
var shelveset = shelvesets.First();

var destinationRef = "refs/heads/" + destinationBranch;
if (File.Exists(Path.Combine(remote.Repository.GitDir, destinationRef)))
{
_stdout.WriteLine(" {0,-20} {1,-20}", shelveset.OwnerName, shelveset.Name);
_stdout.WriteLine("ERROR: Destination branch (" + destinationBranch + ") already exists!");
return GitTfsExitCodes.ForceRequired;
}

// Don't need this because we're just adding a branch.
//var worktreeStatus = remote.Repository.Command("ls-files", "--deleted", "--modified", "--others",
// "--exclude-standard");
//if(!string.IsNullOrEmpty(worktreeStatus))
//{
// _stdout.WriteLine("ERROR: You have a dirty working tree:");
// _stdout.Write(worktreeStatus);
// return GitTfsExitCodes.InvalidPrecondition;
//}

var change = VersionControl.QueryShelvedChanges(shelveset).Single();
var gremote = (GitTfsRemote) remote;
//var tfsChangeset = new FakeTfsChangeset(change);
var wrapperForVersionControlServer =
_bridge.Wrap<WrapperForVersionControlServer, VersionControlServer>(VersionControl);
var fakeChangeset = new FakeChangeset(shelveset, change, wrapperForVersionControlServer, _bridge);
var tfsChangeset = new TfsChangeset(remote.Tfs, fakeChangeset)
{Summary = new TfsChangesetInfo {Remote = remote}};
gremote.Apply(tfsChangeset, destinationRef);
_stdout.WriteLine("Created branch " + destinationBranch + " from shelveset \"" + shelvesetName + "\".");
}
else
return GitTfsExitCodes.OK;
}
class FakeChangeset : IChangeset
{
private readonly Shelveset _shelveset;
private readonly PendingSet _pendingSet;
private readonly IVersionControlServer _versionControlServer;
private readonly TfsApiBridge _bridge;

public FakeChangeset(Shelveset shelveset, PendingSet pendingSet, IVersionControlServer versionControlServer, TfsApiBridge bridge)
{
_shelveset = shelveset;
_versionControlServer = versionControlServer;
_bridge = bridge;
_pendingSet = pendingSet;
}

public IChange[] Changes
{
get { return _pendingSet.PendingChanges.Select(x => new FakeChange(x, _bridge)).Cast<IChange>().ToArray(); }
}

public string Committer
{
get { return _pendingSet.OwnerName; }
}

public DateTime CreationDate
{
get { return _shelveset.CreationDate; }
}

public string Comment
{
get { return _shelveset.Comment; }
}

public int ChangesetId
{
get { return -1; }
}

public IVersionControlServer VersionControlServer
{
get { return _versionControlServer; }
}
}
class FakeChange : IChange
{
private readonly PendingChange _pendingChange;
private readonly TfsApiBridge _bridge;

public FakeChange(PendingChange pendingChange, TfsApiBridge bridge)
{
_pendingChange = pendingChange;
_bridge = bridge;
}

public TfsChangeType ChangeType
{
get { return _bridge.Convert<TfsChangeType>(_pendingChange.ChangeType); }
}

public IItem Item
{
get { return new FakeItem(_pendingChange, _bridge); }
}
}
class FakeItem : IItem
{
private readonly PendingChange _pendingChange;
private readonly TfsApiBridge _bridge;

public FakeItem(PendingChange pendingChange, TfsApiBridge bridge)
{
_pendingChange = pendingChange;
_bridge = bridge;
}

public IVersionControlServer VersionControlServer
{
get { throw new NotImplementedException(); }
}

public int ChangesetId
{
get { throw new NotImplementedException(); }
}

public string ServerItem
{
get { return _pendingChange.ServerItem; }
}

public decimal DeletionId
{
get { return _pendingChange.DeletionId; }
}

public TfsItemType ItemType
{
get { return _bridge.Convert<TfsItemType>(_pendingChange.ItemType); }
}

public int ItemId
{
get { throw new NotImplementedException(); }
}

public void DownloadFile(string file)
{
throw new NotImplementedException();
_pendingChange.DownloadShelvedFile(file);
}
}

Expand Down
5 changes: 2 additions & 3 deletions GitTfs/Commands/Unshelve.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace Sep.Git.Tfs.Commands
{
[Pluggable("unshelve")]
[Description("unshelve [options] (-l | shelveset-name [ref-to-shelve]")]
[Description("unshelve [options] (-l | shelveset-name destination-branch)")]
[RequiresValidGitRepository]
public class Unshelve : GitTfsCommand
{
Expand Down Expand Up @@ -42,8 +42,7 @@ public int Run(IList<string> args)
{
// TODO -- let the remote be specified on the command line.
var remote = _globals.Repository.ReadAllTfsRemotes().First();
remote.Tfs.Unshelve(this, args);
return GitTfsExitCodes.OK;
return remote.Tfs.Unshelve(this, remote, args);
}
}
}
2 changes: 1 addition & 1 deletion GitTfs/Core/GitRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public GitRepository(TextWriter stdout, string gitDir, IContainer container, Glo
_repository = new Repository(new DirectoryInfo(gitDir));
}

private string GitDir { get; set; }
public string GitDir { get; set; }
public string WorkingCopyPath { get; set; }
public string WorkingCopySubdir { get; set; }

Expand Down
7 changes: 7 additions & 0 deletions GitTfs/Core/GitTfsRemote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ public void FetchWithMerge(long mergeChangesetId, params string[] parentCommitsH
}
}

public void Apply(ITfsChangeset changeset, string destinationRef)
{
var log = Apply(MaxCommitHash, changeset);
var commit = Commit(log);
Repository.CommandNoisy("update-ref", destinationRef, commit);
}

public void QuickFetch()
{
var changeset = Tfs.GetLatestChangeset(this);
Expand Down
12 changes: 12 additions & 0 deletions GitTfs/Core/IGitHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,21 @@ namespace Sep.Git.Tfs.Core
{
public interface IGitHelpers
{
/// <summary>
/// Runs the given git command, and returns the contents of its STDOUT.
/// </summary>
string Command(params string[] command);
/// <summary>
/// Runs the given git command, and returns the first line of its STDOUT.
/// </summary>
string CommandOneline(params string[] command);
/// <summary>
/// Runs the given git command, and passes STDOUT through to the current process's STDOUT.
/// </summary>
void CommandNoisy(params string[] command);
/// <summary>
/// Runs the given git command, and redirects STDOUT to the provided action.
/// </summary>
void CommandOutputPipe(Action<TextReader> func, params string[] command);
void CommandInputPipe(Action<TextWriter> action, params string[] command);
void CommandInputOutputPipe(Action<TextWriter, TextReader> interact, params string[] command);
Expand Down
1 change: 1 addition & 0 deletions GitTfs/Core/IGitRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Sep.Git.Tfs.Core
{
public interface IGitRepository : IGitHelpers
{
string GitDir { get; set; }
IEnumerable<IGitTfsRemote> ReadAllTfsRemotes();
IGitTfsRemote ReadTfsRemote(string remoteId);
void /*or IGitTfsRemote*/ CreateTfsRemote(string remoteId, string tfsUrl, string tfsRepositoryPath, RemoteOptions remoteOptions);
Expand Down
2 changes: 1 addition & 1 deletion GitTfs/Core/TfsInterop/ITfsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public interface ITfsHelper
IChangeset GetChangeset(int changesetId);
bool MatchesUrl(string tfsUrl);
bool HasShelveset(string shelvesetName);
void Unshelve(Unshelve unshelve, IList<string> args);
int Unshelve(Unshelve unshelve, IGitTfsRemote remote, IList<string> args);
bool CanShowCheckinDialog { get; }
long ShowCheckinDialog(IWorkspace workspace, IPendingChange[] pendingChanges, IEnumerable<IWorkItemCheckedInfo> checkedInfos, string checkinComment);
void CleanupWorkspaces(string workingDirectory);
Expand Down
1 change: 1 addition & 0 deletions GitTfs/GitTfsExitCodes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ public static class GitTfsExitCodes
public const int Help = 1;
public const int InvalidArguments = 2;
public const int ForceRequired = 3;
public const int InvalidPrecondition = 4;
}
}

0 comments on commit 37fb702

Please sign in to comment.