# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: /home/ondra/storage/netbeans/core-main # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: libs.git/apichanges.xml --- libs.git/apichanges.xml +++ libs.git/apichanges.xml @@ -111,6 +111,23 @@ + New method for updating a reference (branch) to a new commit id. + + + + + +

In order to simplify a trivial use-case of merging a remote branch into a local branch + not currently checked-out we're adding a new method able to update the local branch to + the new id. It is possible only if the branch requires a fast-forward merge (does not + contain any unpushed commits). +

+
+ + +
+ + New methods in ProgressMonitor informing about the progress of command's subtasks. Index: libs.git/manifest.mf --- libs.git/manifest.mf +++ libs.git/manifest.mf @@ -1,4 +1,4 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.libs.git/1 OpenIDE-Module-Localizing-Bundle: org/netbeans/libs/git/Bundle.properties -OpenIDE-Module-Specification-Version: 1.23 +OpenIDE-Module-Specification-Version: 1.24 Index: libs.git/src/org/netbeans/libs/git/GitClient.java --- libs.git/src/org/netbeans/libs/git/GitClient.java +++ libs.git/src/org/netbeans/libs/git/GitClient.java @@ -101,6 +101,7 @@ import org.netbeans.libs.git.jgit.commands.SubmoduleInitializeCommand; import org.netbeans.libs.git.jgit.commands.SubmoduleStatusCommand; import org.netbeans.libs.git.jgit.commands.SubmoduleUpdateCommand; +import org.netbeans.libs.git.jgit.commands.UpdateRefCommand; import org.netbeans.libs.git.progress.FileListener; import org.netbeans.libs.git.progress.NotificationListener; import org.netbeans.libs.git.progress.ProgressMonitor; @@ -1099,6 +1100,25 @@ cmd.execute(); return cmd.getModifiedIgnoreFiles(); } + + /** + * Updates a given reference to a new id. If the new id is also a ref then + * the ref will be updated to the same commit id referenced by the new id. + * The update will not be permitted if the reference is not merged into the + * new commit (i.e. contains its private commits). + * + * @param referenceName name of the ref to update + * @param newId the new reference id + * @param monitor progress monitor + * @return result result of the update + * @throws GitException an unexpected error happens + */ + public GitRefUpdateResult updateReference (String referenceName, String newId, ProgressMonitor monitor) throws GitException { + Repository repository = gitRepository.getRepository(); + UpdateRefCommand cmd = new UpdateRefCommand(repository, getClassFactory(), referenceName, newId, monitor); + cmd.execute(); + return cmd.getResult(); + } /** * Updates submodules. An equivalent to submodule update command. Index: libs.git/src/org/netbeans/libs/git/jgit/commands/UpdateRefCommand.java --- libs.git/src/org/netbeans/libs/git/jgit/commands/UpdateRefCommand.java +++ libs.git/src/org/netbeans/libs/git/jgit/commands/UpdateRefCommand.java @@ -0,0 +1,114 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2010 Sun Microsystems, Inc. + */ + +package org.netbeans.libs.git.jgit.commands; + +import java.io.IOException; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectIdRef; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.lib.Repository; +import org.netbeans.libs.git.GitException; +import org.netbeans.libs.git.GitRefUpdateResult; +import org.netbeans.libs.git.jgit.GitClassFactory; +import org.netbeans.libs.git.progress.ProgressMonitor; + +/** + * + * @author ondra + */ +public class UpdateRefCommand extends GitCommand { + private final String revision; + private final String refName; + private GitRefUpdateResult result; + + public UpdateRefCommand (Repository repository, GitClassFactory gitFactory, String refName, String revision, ProgressMonitor monitor) { + super(repository, gitFactory, monitor); + this.refName = refName; + this.revision = revision; + } + + @Override + protected void run () throws GitException { + Repository repository = getRepository(); + try { + + Ref ref = repository.getRef(refName); + if (ref == null || ref.isSymbolic()) { + // currently unable to update symbolic references + result = GitRefUpdateResult.valueOf(RefUpdate.Result.NOT_ATTEMPTED.name()); + return; + } + + Ref newRef = repository.getRef(revision); + String name; + if (newRef == null) { + ObjectId id = repository.resolve(revision); + newRef = new ObjectIdRef.Unpeeled(Ref.Storage.LOOSE, id.name(),id.copy()); + name = newRef.getName(); + } else { + name = revision; + } + + RefUpdate u = repository.updateRef(ref.getName()); + u.setNewObjectId(newRef.isPeeled() ? newRef.getPeeledObjectId() : newRef.getObjectId()); + u.setRefLogMessage("merge " + name + ": Fast-forward", false); //NOI18N + u.update(); + result = GitRefUpdateResult.valueOf((u.getResult() == null + ? RefUpdate.Result.NOT_ATTEMPTED + : u.getResult()).name()); + } catch (IOException ex) { + throw new GitException(ex); + } + } + + @Override + protected String getCommandDescription () { + return new StringBuilder("git update-ref ").append(refName).append(revision).toString(); //NOI18N + } + + public GitRefUpdateResult getResult () { + return result; + } + +} Index: libs.git/test/unit/src/org/netbeans/libs/git/jgit/CommandsTestSuite.java --- libs.git/test/unit/src/org/netbeans/libs/git/jgit/CommandsTestSuite.java +++ libs.git/test/unit/src/org/netbeans/libs/git/jgit/CommandsTestSuite.java @@ -80,6 +80,7 @@ import org.netbeans.libs.git.jgit.commands.SubmoduleTest; import org.netbeans.libs.git.jgit.commands.TagTest; import org.netbeans.libs.git.jgit.commands.UnignoreTest; +import org.netbeans.libs.git.jgit.commands.UpdateRefTest; /** * @@ -128,6 +129,7 @@ suite.addTestSuite(SubmoduleTest.class); suite.addTestSuite(TagTest.class); suite.addTestSuite(UnignoreTest.class); + suite.addTestSuite(UpdateRefTest.class); return suite; } Index: libs.git/test/unit/src/org/netbeans/libs/git/jgit/commands/UpdateRefTest.java --- libs.git/test/unit/src/org/netbeans/libs/git/jgit/commands/UpdateRefTest.java +++ libs.git/test/unit/src/org/netbeans/libs/git/jgit/commands/UpdateRefTest.java @@ -0,0 +1,156 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2010 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2010 Sun Microsystems, Inc. + */ + +package org.netbeans.libs.git.jgit.commands; + +import java.io.File; +import java.io.IOException; +import org.eclipse.jgit.lib.ReflogReader; +import org.eclipse.jgit.lib.Repository; +import org.netbeans.libs.git.GitClient; +import org.netbeans.libs.git.GitRefUpdateResult; +import org.netbeans.libs.git.GitRevisionInfo; +import org.netbeans.libs.git.jgit.AbstractGitTestCase; + +/** + * + * @author ondra + */ +public class UpdateRefTest extends AbstractGitTestCase { + private Repository repository; + private File workDir; + + public UpdateRefTest (String testName) throws IOException { + super(testName); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + workDir = getWorkingDirectory(); + repository = getRepository(getLocalGitRepository()); + } + + public void testNotAttempted () throws Exception { + File f = new File(workDir, "f"); + write(f, "init"); + add(f); + commit(f); + + write(f, "modi"); + add(f); + commit(f); + + GitClient client = getClient(workDir); + GitRevisionInfo info = client.log("HEAD", NULL_PROGRESS_MONITOR); + + client.reset("HEAD~1", GitClient.ResetType.HARD, NULL_PROGRESS_MONITOR); + + GitRefUpdateResult res = client.updateReference("HEAD", info.getRevision(), NULL_PROGRESS_MONITOR); + assertEquals(GitRefUpdateResult.NOT_ATTEMPTED, res); + } + + public void testMoveMergeCommit () throws Exception { + File f = new File(workDir, "f"); + write(f, "init"); + add(f); + commit(f); + + write(f, "modif"); + add(f); + commit(f); + + GitClient client = getClient(workDir); + GitRevisionInfo info = client.log("HEAD", NULL_PROGRESS_MONITOR); + + client.reset("HEAD~1", GitClient.ResetType.HARD, NULL_PROGRESS_MONITOR); + + GitRefUpdateResult res = client.updateReference("master", info.getRevision(), NULL_PROGRESS_MONITOR); + assertEquals(GitRefUpdateResult.FAST_FORWARD, res); + ReflogReader reflogReader = repository.getReflogReader("master"); + assertEquals("merge " + info.getRevision() + ": Fast-forward", reflogReader.getLastEntry().getComment()); + } + + public void testMoveMergeRef () throws Exception { + File f = new File(workDir, "f"); + write(f, "init"); + add(f); + commit(f); + + write(f, "modif"); + add(f); + commit(f); + + GitClient client = getClient(workDir); + client.createBranch("BRANCH", "HEAD", NULL_PROGRESS_MONITOR); + + client.reset("HEAD~1", GitClient.ResetType.HARD, NULL_PROGRESS_MONITOR); + + GitRefUpdateResult res = client.updateReference("master", "BRANCH", NULL_PROGRESS_MONITOR); + assertEquals(GitRefUpdateResult.FAST_FORWARD, res); + ReflogReader reflogReader = repository.getReflogReader("master"); + assertEquals("merge BRANCH: Fast-forward", reflogReader.getLastEntry().getComment()); + } + + // must fail if would end in a non FF update + public void testMoveMergeRejected () throws Exception { + File f = new File(workDir, "f"); + write(f, "init"); + add(f); + commit(f); + + write(f, "modif"); + add(f); + commit(f); + + GitClient client = getClient(workDir); + client.createBranch("BRANCH", "HEAD", NULL_PROGRESS_MONITOR); + + client.reset("HEAD~1", GitClient.ResetType.HARD, NULL_PROGRESS_MONITOR); + + write(f, "modif2"); + add(f); + commit(f); + GitRefUpdateResult res = client.updateReference("master", "BRANCH", NULL_PROGRESS_MONITOR); + assertEquals(GitRefUpdateResult.REJECTED, res); + } +}