Exemple #1
0
        public static IEnumerable <DiffEntry> CompareCommits(NGit.Repository repo, AnyObjectId reference, ObjectId compared)
        {
            var diff = new NGit.Api.Git(repo).Diff();

            var firstTree = new CanonicalTreeParser();

            firstTree.Reset(repo.NewObjectReader(), new RevWalk(repo).ParseTree(reference));

            var secondTree = new CanonicalTreeParser();

            secondTree.Reset(repo.NewObjectReader(), new RevWalk(repo).ParseTree(compared));

            diff.SetNewTree(firstTree);
            if (compared != ObjectId.ZeroId)
            {
                diff.SetOldTree(secondTree);
            }

            return(diff.Call());
        }
Exemple #2
0
        /// <returns>the commit if we had to do a commit, otherwise null</returns>
        /// <exception cref="NGit.Api.Errors.GitAPIException">NGit.Api.Errors.GitAPIException
        ///     </exception>
        /// <exception cref="System.IO.IOException">System.IO.IOException</exception>
        private RevCommit ContinueRebase()
        {
            // if there are still conflicts, we throw a specific Exception
            DirCache dc = repo.ReadDirCache();
            bool     hasUnmergedPaths = dc.HasUnmergedPaths();

            if (hasUnmergedPaths)
            {
                throw new UnmergedPathsException();
            }
            // determine whether we need to commit
            TreeWalk treeWalk = new TreeWalk(repo);

            treeWalk.Reset();
            treeWalk.Recursive = true;
            treeWalk.AddTree(new DirCacheIterator(dc));
            ObjectId id = repo.Resolve(Constants.HEAD + "^{tree}");

            if (id == null)
            {
                throw new NoHeadException(JGitText.Get().cannotRebaseWithoutCurrentHead);
            }
            treeWalk.AddTree(id);
            treeWalk.Filter = TreeFilter.ANY_DIFF;
            bool needsCommit = treeWalk.Next();

            treeWalk.Release();
            if (needsCommit)
            {
                CommitCommand commit = new Git(repo).Commit();
                commit.SetMessage(ReadFile(rebaseDir, MESSAGE));
                commit.SetAuthor(ParseAuthor());
                return(commit.Call());
            }
            return(null);
        }
		public IEnumerable<string> GetRemoteBranches (string remoteName)
		{
			var list = new NGit.Api.Git (RootRepository).BranchList ().SetListMode (ListBranchCommand.ListMode.REMOTE);
			foreach (var item in list.Call ()) {
				string name = NGit.Repository.ShortenRefName (item.GetName ());
				if (name.StartsWith (remoteName + "/", StringComparison.Ordinal))
					yield return name.Substring (remoteName.Length + 1);
			}
		}
		public void AddTag (string name, Revision rev, string message)
		{
			var addTag = new NGit.Api.Git (RootRepository).Tag ();
			var gitRev = (GitRevision)rev;

			addTag.SetName (name).SetMessage (message).SetObjectId (gitRev.Commit);
			addTag.SetObjectId (gitRev.Commit).SetTagger (new PersonIdent (RootRepository));
			addTag.Call ();
		}
		public IEnumerable<string> GetTags ()
		{
			var list = new NGit.Api.Git (RootRepository).TagList ();
			foreach (var item in list.Call ()) {
				string name = NGit.Repository.ShortenRefName (item.GetName ());
				yield return name;
			}
		}
		public IEnumerable<Branch> GetBranches ()
		{
			var list = new NGit.Api.Git (RootRepository).BranchList ().SetListMode (ListBranchCommand.ListMode.HEAD);
			foreach (var item in list.Call ()) {
				string name = NGit.Repository.ShortenRefName (item.GetName ());
				Branch br = new Branch ();
				br.Name = name;
				br.Tracking = GitUtil.GetUpstreamSource (RootRepository, name);
				yield return br;
			}
		}
		public void CreateBranch (string name, string trackSource)
		{
			var create = new NGit.Api.Git (RootRepository).BranchCreate ();
			if (!String.IsNullOrEmpty (trackSource))
				create.SetStartPoint (trackSource);
			create.SetName (name);
			create.Call ();
		}
		public void CreateBranchFromCommit (string name, RevCommit id)
		{
			var create = new NGit.Api.Git (RootRepository).BranchCreate ();
			if (id != null)
				create.SetStartPoint (id);
			create.SetName (name);
			create.Call ();
		}
Exemple #9
0
        /// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception>
        /// <exception cref="System.IO.IOException"></exception>
        /// <exception cref="NGit.Api.Errors.NoHeadException"></exception>
        /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception>
        private RebaseResult InitFilesAndRewind()
        {
            // we need to store everything into files so that we can implement
            // --skip, --continue, and --abort
            Ref head = repo.GetRef(Constants.HEAD);

            if (head == null || head.GetObjectId() == null)
            {
                throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
                                                                    , Constants.HEAD));
            }
            string headName;

            if (head.IsSymbolic())
            {
                headName = head.GetTarget().GetName();
            }
            else
            {
                headName = "detached HEAD";
            }
            ObjectId headId = head.GetObjectId();

            if (headId == null)
            {
                throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
                                                                    , Constants.HEAD));
            }
            RevCommit headCommit = walk.LookupCommit(headId);
            RevCommit upstream   = walk.LookupCommit(upstreamCommit.Id);

            if (walk.IsMergedInto(upstream, headCommit))
            {
                return(RebaseResult.UP_TO_DATE_RESULT);
            }
            else
            {
                if (walk.IsMergedInto(headCommit, upstream))
                {
                    // head is already merged into upstream, fast-foward
                    monitor.BeginTask(MessageFormat.Format(JGitText.Get().resettingHead, upstreamCommit
                                                           .GetShortMessage()), ProgressMonitor.UNKNOWN);
                    CheckoutCommit(upstreamCommit);
                    monitor.EndTask();
                    UpdateHead(headName, upstreamCommit);
                    return(RebaseResult.FAST_FORWARD_RESULT);
                }
            }
            monitor.BeginTask(JGitText.Get().obtainingCommitsForCherryPick, ProgressMonitor.UNKNOWN
                              );
            // determine the commits to be applied
            LogCommand           cmd            = new Git(repo).Log().AddRange(upstreamCommit, headCommit);
            Iterable <RevCommit> commitsToUse   = cmd.Call();
            IList <RevCommit>    cherryPickList = new AList <RevCommit>();

            foreach (RevCommit commit in commitsToUse)
            {
                if (commit.ParentCount != 1)
                {
                    throw new JGitInternalException(JGitText.Get().canOnlyCherryPickCommitsWithOneParent
                                                    );
                }
                cherryPickList.AddItem(commit);
            }
            Sharpen.Collections.Reverse(cherryPickList);
            // create the folder for the meta information
            FileUtils.Mkdir(rebaseDir);
            CreateFile(repo.Directory, Constants.ORIG_HEAD, headId.Name);
            CreateFile(rebaseDir, REBASE_HEAD, headId.Name);
            CreateFile(rebaseDir, HEAD_NAME, headName);
            CreateFile(rebaseDir, ONTO, upstreamCommit.Name);
            CreateFile(rebaseDir, INTERACTIVE, string.Empty);
            BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream
                                                                              (new FilePath(rebaseDir, GIT_REBASE_TODO)), Constants.CHARACTER_ENCODING));

            fw.Write("# Created by EGit: rebasing " + upstreamCommit.Name + " onto " + headId
                     .Name);
            fw.NewLine();
            try
            {
                StringBuilder sb     = new StringBuilder();
                ObjectReader  reader = walk.GetObjectReader();
                foreach (RevCommit commit_1 in cherryPickList)
                {
                    sb.Length = 0;
                    sb.Append(RebaseCommand.Action.PICK.ToToken());
                    sb.Append(" ");
                    sb.Append(reader.Abbreviate(commit_1).Name);
                    sb.Append(" ");
                    sb.Append(commit_1.GetShortMessage());
                    fw.Write(sb.ToString());
                    fw.NewLine();
                }
            }
            finally
            {
                fw.Close();
            }
            monitor.EndTask();
            // we rewind to the upstream commit
            monitor.BeginTask(MessageFormat.Format(JGitText.Get().rewinding, upstreamCommit.GetShortMessage
                                                       ()), ProgressMonitor.UNKNOWN);
            bool checkoutOk = false;

            try
            {
                checkoutOk = CheckoutCommit(upstreamCommit);
            }
            finally
            {
                if (!checkoutOk)
                {
                    FileUtils.Delete(rebaseDir, FileUtils.RECURSIVE);
                }
            }
            monitor.EndTask();
            return(null);
        }
Exemple #10
0
        /// <exception cref="NGit.Api.Errors.RefNotFoundException"></exception>
        /// <exception cref="System.IO.IOException"></exception>
        /// <exception cref="NGit.Api.Errors.NoHeadException"></exception>
        /// <exception cref="NGit.Api.Errors.JGitInternalException"></exception>
        private RebaseResult InitFilesAndRewind()
        {
            // we need to store everything into files so that we can implement
            // --skip, --continue, and --abort
            // first of all, we determine the commits to be applied
            IList <RevCommit> cherryPickList = new AList <RevCommit>();
            Ref head = repo.GetRef(Constants.HEAD);

            if (head == null || head.GetObjectId() == null)
            {
                throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
                                                                    , Constants.HEAD));
            }
            string headName;

            if (head.IsSymbolic())
            {
                headName = head.GetTarget().GetName();
            }
            else
            {
                headName = "detached HEAD";
            }
            ObjectId headId = head.GetObjectId();

            if (headId == null)
            {
                throw new RefNotFoundException(MessageFormat.Format(JGitText.Get().refNotResolved
                                                                    , Constants.HEAD));
            }
            RevCommit headCommit = walk.LookupCommit(headId);

            monitor.BeginTask(JGitText.Get().obtainingCommitsForCherryPick, ProgressMonitor.UNKNOWN
                              );
            LogCommand           cmd          = new Git(repo).Log().AddRange(upstreamCommit, headCommit);
            Iterable <RevCommit> commitsToUse = cmd.Call();

            foreach (RevCommit commit in commitsToUse)
            {
                cherryPickList.AddItem(commit);
            }
            // if the upstream commit is in a direct line to the current head,
            // the log command will not report any commits; in this case,
            // we create the cherry-pick list ourselves
            if (cherryPickList.IsEmpty())
            {
                Iterable <RevCommit> parents = new Git(repo).Log().Add(upstreamCommit).Call();
                foreach (RevCommit parent in parents)
                {
                    if (parent.Equals(headCommit))
                    {
                        break;
                    }
                    if (parent.ParentCount != 1)
                    {
                        throw new JGitInternalException(JGitText.Get().canOnlyCherryPickCommitsWithOneParent
                                                        );
                    }
                    cherryPickList.AddItem(parent);
                }
            }
            // nothing to do: return with UP_TO_DATE_RESULT
            if (cherryPickList.IsEmpty())
            {
                return(RebaseResult.UP_TO_DATE_RESULT);
            }
            Sharpen.Collections.Reverse(cherryPickList);
            // create the folder for the meta information
            FileUtils.Mkdir(rebaseDir);
            CreateFile(repo.Directory, Constants.ORIG_HEAD, headId.Name);
            CreateFile(rebaseDir, REBASE_HEAD, headId.Name);
            CreateFile(rebaseDir, HEAD_NAME, headName);
            CreateFile(rebaseDir, ONTO, upstreamCommit.Name);
            CreateFile(rebaseDir, INTERACTIVE, string.Empty);
            BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream
                                                                              (new FilePath(rebaseDir, GIT_REBASE_TODO)), Constants.CHARACTER_ENCODING));

            fw.Write("# Created by EGit: rebasing " + upstreamCommit.Name + " onto " + headId
                     .Name);
            fw.NewLine();
            try
            {
                StringBuilder sb     = new StringBuilder();
                ObjectReader  reader = walk.GetObjectReader();
                foreach (RevCommit commit_1 in cherryPickList)
                {
                    sb.Length = 0;
                    sb.Append(RebaseCommand.Action.PICK.ToToken());
                    sb.Append(" ");
                    sb.Append(reader.Abbreviate(commit_1).Name);
                    sb.Append(" ");
                    sb.Append(commit_1.GetShortMessage());
                    fw.Write(sb.ToString());
                    fw.NewLine();
                }
            }
            finally
            {
                fw.Close();
            }
            monitor.EndTask();
            // we rewind to the upstream commit
            monitor.BeginTask(MessageFormat.Format(JGitText.Get().rewinding, upstreamCommit.GetShortMessage
                                                       ()), ProgressMonitor.UNKNOWN);
            CheckoutCommit(upstreamCommit);
            monitor.EndTask();
            return(null);
        }
        /// <summary>
        /// Requires absolute path
        /// </summary>
        /// <param name="fileName"></param>
        public void UnStageFile(string fileName)
        {
            if (!this.HasGitRepository) return;

            var fileNameRel = GetRelativeFileName(fileName);

            if (GitBash.Exists)
            {
                if (head == null)
                {
                    GitBash.Run(string.Format("rm --cached -- \"{0}\"", fileNameRel), this.GitWorkingDirectory);
                }
                else
                {
                    GitBash.Run(string.Format("reset -- \"{0}\"", fileNameRel), this.GitWorkingDirectory);
                }
            }
            else
            {
                ResetCommand resetCommand = new Git(repository).Reset();
                resetCommand.AddPath(GetRelativeFileNameForGit(fileName));
                resetCommand.SetRef(Constants.HEAD);
                resetCommand.Call();
            }

            this.cache.Remove(GetCacheKey(fileName));
            this.changedFiles = null;
        }
        /// <summary>
        /// Requires absolute path
        /// </summary>
        /// <param name="fileName"></param>
        public void StageFile(string fileName)
        {
            if (!this.HasGitRepository) return;
            //var index = repository.GetIndex();
            //index.RereadIfNecessary();
            if (GitBash.Exists)
            {
                if (File.Exists(fileName))
                {
                    GitBash.Run(string.Format("add \"{0}\"", GetRelativeFileName(fileName)), this.GitWorkingDirectory);
                }
                else
                {
                    GitBash.Run(string.Format("rm --cached -- \"{0}\"", GetRelativeFileName(fileName)), this.GitWorkingDirectory);
                }
            }
            else
            {
                if (File.Exists(fileName))
                {
                    AddCommand addCommand = new Git(repository).Add();
                    addCommand.AddFilepattern(GetRelativeFileNameForGit(fileName));
                    addCommand.Call();
                }
                else
                {
                    RmCommand rmCommand = new Git(repository).Rm();
                    rmCommand.AddFilepattern(GetRelativeFileNameForGit(fileName));
                    rmCommand.Call();
                }
            }

            this.cache.Remove(GetCacheKey(fileName));
            this.changedFiles = null;
        }
		public static IEnumerable<DiffEntry> CompareCommits (NGit.Repository repo, AnyObjectId reference, ObjectId compared)
		{
			var diff = new NGit.Api.Git (repo).Diff ();

			var firstTree = new CanonicalTreeParser ();
			firstTree.Reset (repo.NewObjectReader (), new RevWalk (repo).ParseTree (reference));
			diff.SetNewTree (firstTree);
			
			if (compared != ObjectId.ZeroId) {
				var secondTree = new CanonicalTreeParser ();
				secondTree.Reset (repo.NewObjectReader (), new RevWalk (repo).ParseTree (compared));

				if (compared != ObjectId.ZeroId)
					diff.SetOldTree (secondTree);
			}
			return diff.Call ();
		}
		public void SwitchToBranch (IProgressMonitor monitor, string branch)
		{
			monitor.BeginTask (GettextCatalog.GetString ("Switching to branch {0}", branch), GitService.StashUnstashWhenSwitchingBranches ? 4 : 2);
			
			// Get a list of files that are different in the target branch
			IEnumerable<DiffEntry> statusList = GitUtil.GetChangedFiles (RootRepository, branch);
			
			StashCollection stashes = null;
			Stash stash = null;
			
			if (GitService.StashUnstashWhenSwitchingBranches) {
				stashes = GitUtil.GetStashes (RootRepository);
				
				// Remove the stash for this branch, if exists
				string currentBranch = GetCurrentBranch ();
				stash = GetStashForBranch (stashes, currentBranch);
				if (stash != null)
					stashes.Remove (stash);
				
				// Create a new stash for the branch. This allows switching branches
				// without losing local changes
				using (var gm = new GitMonitor (monitor))
					stash = stashes.Create (gm, GetStashName (currentBranch));
			
				monitor.Step (1);
			}

			// Replace with NGit.Api.Git ().Checkout ()
			// Switch to the target branch
			var checkout = new NGit.Api.Git (RootRepository).Checkout ();
			checkout.SetName (branch);
			try {
				checkout.Call ();
			} finally {
				// Restore the branch stash
				if (GitService.StashUnstashWhenSwitchingBranches) {
					stash = GetStashForBranch (stashes, branch);
					if (stash != null) {
						using (var gm = new GitMonitor (monitor))
							stash.Apply (gm);
						stashes.Remove (stash);
					}
					monitor.Step (1);
				}
			}
			// Notify file changes
			
			NotifyFileChanges (monitor, statusList);
			
			if (BranchSelectionChanged != null)
				BranchSelectionChanged (this, EventArgs.Empty);
			
			monitor.EndTask ();
		}
		public void Push (IProgressMonitor monitor, string remote, string remoteBranch)
		{
			string remoteRef = "refs/heads/" + remoteBranch;
			IEnumerable<PushResult> res;

			var push = new NGit.Api.Git (RootRepository).Push ();

			// We only have one pushed branch.
			push.SetRemote (remote).SetRefSpecs (new RefSpec (remoteRef));
			using (var gm = new GitMonitor (monitor)) {
				push.SetProgressMonitor (gm);
				res = push.Call ();
			}

			foreach (var pr in res) {
				var remoteUpdate = pr.GetRemoteUpdate (remoteRef);

				switch (remoteUpdate.GetStatus ()) {
					case RemoteRefUpdate.Status.UP_TO_DATE: monitor.ReportSuccess (GettextCatalog.GetString ("Remote branch is up to date.")); break;
					case RemoteRefUpdate.Status.REJECTED_NODELETE: monitor.ReportError (GettextCatalog.GetString ("The server is configured to deny deletion of the branch"), null); break;
					case RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD: monitor.ReportError (GettextCatalog.GetString ("The update is a non-fast-forward update. Merge the remote changes before pushing again."), null); break;
					case RemoteRefUpdate.Status.OK:
						monitor.ReportSuccess (GettextCatalog.GetString ("Push operation successfully completed."));
						// Update the remote branch
						ObjectId headId = remoteUpdate.GetNewObjectId ();
						RefUpdate updateRef = RootRepository.UpdateRef (Constants.R_REMOTES + remote + "/" + remoteBranch);
						updateRef.SetNewObjectId(headId);
						updateRef.Update();
						break;
					default:
						string msg = remoteUpdate.GetMessage ();
						msg = !string.IsNullOrEmpty (msg) ? msg : GettextCatalog.GetString ("Push operation failed");
						monitor.ReportError (msg, null);
						break;
				}
			}
		}
		public void Fetch (IProgressMonitor monitor)
		{
			string remote = GetCurrentRemote ();
			if (remote == null)
				throw new InvalidOperationException ("No remotes defined");

			monitor.Log.WriteLine (GettextCatalog.GetString ("Fetching from '{0}'", remote));
			var fetch = new NGit.Api.Git (RootRepository).Fetch ();
			using (var gm = new GitMonitor (monitor)) {
				fetch.SetRemote (remote);
				fetch.SetProgressMonitor (gm);
				fetch.Call ();
			}
			monitor.Step (1);
		}
		public bool Rebase ()
		{
			NGit.Api.Git git = new NGit.Api.Git (repo);
			
			if (aborted)
				return false;
			
			if (starting) {
				ObjectId headId = repo.Resolve (Constants.HEAD + "^{commit}");
				RevCommit headCommit = rw.ParseCommit (headId);
				oldHead = headCommit;
				ObjectId upstreamId = repo.Resolve (upstreamRef);
				RevCommit upstreamCommit = rw.ParseCommit (upstreamId);
				
				oldHead = headCommit;
				lastGoodHead = upstreamId;
				commitChain = new List<RevCommit> ();
			
				LogCommand cmd = new NGit.Api.Git(repo).Log().AddRange(upstreamId, headCommit);
				foreach (RevCommit commit in cmd.Call())
					commitChain.Add(commit);
				
				commitChain.Reverse ();
				currentMergeIndex = 0;
				
				// Checkout the upstream commit
				// Reset head to upstream
				GitUtil.HardReset (repo, upstreamRef);
				
				string rebaseDir = Path.Combine (repo.Directory, "rebase-apply");
				if (!Directory.Exists (rebaseDir))
					Directory.CreateDirectory (rebaseDir);
				
				string rebasingFile = Path.Combine (rebaseDir, "rebasing");
				if (!File.Exists (rebasingFile))
					File.WriteAllBytes (rebasingFile, new byte[0]);
				
				starting = false;
				monitor.BeginTask ("Applying local commits", commitChain.Count);
			}
			else {
				// Conflicts resolved. Continue.
				NGit.Api.AddCommand cmd = git.Add ();
				var conflicts = LastMergeResult.GetConflicts ();
				foreach (string conflictFile in conflicts.Keys) {
					cmd.AddFilepattern (conflictFile);
				}
				cmd.Call ();
				NGit.Api.CommitCommand commit = git.Commit ();
				commit.SetMessage (currentMergeCommit.GetFullMessage ());
				commit.SetAuthor (currentMergeCommit.GetAuthorIdent ());
				commit.SetCommitter (currentMergeCommit.GetCommitterIdent ());
				commit.Call();
			}
			
			// Merge commit by commit until the current head
			
			while (currentMergeIndex < commitChain.Count) {
				currentMergeCommit = commitChain[currentMergeIndex++];
				mergeResult = GitUtil.CherryPick (repo, currentMergeCommit);
				monitor.Log.WriteLine ("Applied '{0}'", currentMergeCommit.GetShortMessage ());
				monitor.Step (1);
				if (mergeResult.GetMergeStatus () == MergeStatus.CONFLICTING || mergeResult.GetMergeStatus () == MergeStatus.FAILED)
					return false;
				lastGoodHead = mergeResult.GetNewHead ();
			}
			
			monitor.EndTask ();
			CleanRebaseFile ();
			return true;
		}