From e23b09ad6efc35f6574cfefd4467ad20e5212ff2 Mon Sep 17 00:00:00 2001 From: Matthias Sohn Date: Tue, 13 Mar 2018 02:20:29 +0100 Subject: [PATCH] Implement --force option in FetchCommand and CLI fetch command Change-Id: I42cdb57b8fb54ce466d1958391f12f911045327f Signed-off-by: Matthias Sohn --- .../tst/org/eclipse/jgit/pgm/FetchTest.java | 13 ++++++ .../jgit/pgm/internal/CLIText.properties | 1 + .../src/org/eclipse/jgit/pgm/Fetch.java | 6 +++ .../eclipse/jgit/api/FetchCommandTest.java | 19 ++++++++ .../org/eclipse/jgit/api/FetchCommand.java | 43 +++++++++++++++++-- 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/FetchTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/FetchTest.java index 9685d4517..dde1a332d 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/FetchTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/FetchTest.java @@ -91,6 +91,19 @@ public void testFetchDefault() throws Exception { assertEquals(" * [new tag] tag -> tag", result[2]); } + @Test + public void testFetchForceUpdate() throws Exception { + String[] result = execute( + "git fetch test refs/heads/master:refs/remotes/origin/master"); + assertEquals(" * [new branch] master -> origin/master", + result[1]); + assertEquals(" * [new tag] tag -> tag", result[2]); + remoteGit.commit().setAmend(true).setMessage("amended").call(); + result = execute( + "git fetch -f test refs/heads/master:refs/remotes/origin/master"); + assertEquals("", result[0]); + } + @Test public void testFetchNoTags() throws Exception { String[] result = execute("git fetch --no-tags test refs/heads/master:refs/remotes/origin/master"); diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties index cb0ea1bc4..e9370930d 100644 --- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties +++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties @@ -343,6 +343,7 @@ usage_forEachRefOutput=for-each-ref output usage_forceCheckout=when switching branches, proceed even if the index or the working tree differs from HEAD usage_forceClean=required to delete files or directories usage_forceCreateBranchEvenExists=force create branch even exists +usage_forcedFetch=force ref update fetch option usage_forceReplacingAnExistingTag=force replacing an existing tag usage_getAndSetOptions=Get and set repository or global options usage_groups=Restrict manifest projects to ones with specified group(s), use "-" for excluding [default|all|G1,G2,G3|G4,-G5,-G6] diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java index bc7637286..61fd521b8 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java @@ -100,6 +100,9 @@ void notags(@SuppressWarnings("unused") tags = Boolean.FALSE; } + @Option(name = "--force", usage = "usage_forcedFetch", aliases = { "-f" }) + private Boolean force; + private FetchRecurseSubmodulesMode recurseSubmodules; @Option(name = "--recurse-submodules", usage = "usage_recurseSubmodules") @@ -155,6 +158,9 @@ protected void run() throws Exception { if (quiet == null || !quiet.booleanValue()) fetch.setProgressMonitor(new TextProgressMonitor(errw)); fetch.setRecurseSubmodules(recurseSubmodules).setCallback(this); + if (force != null) { + fetch.setForceUpdate(force.booleanValue()); + } FetchResult result = fetch.call(); if (result.getTrackingRefUpdates().isEmpty() diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java index 83a0564c7..cf1afceae 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/FetchCommandTest.java @@ -101,6 +101,25 @@ public void testFetch() throws Exception { db.resolve(tagRef.getObjectId().getName())); } + @Test + public void testForcedFetch() throws Exception { + remoteGit.commit().setMessage("commit").call(); + remoteGit.commit().setMessage("commit2").call(); + git.fetch().setRemote("test") + .setRefSpecs("refs/heads/master:refs/heads/master").call(); + + remoteGit.commit().setAmend(true).setMessage("amended").call(); + FetchResult res = git.fetch().setRemote("test") + .setRefSpecs("refs/heads/master:refs/heads/master").call(); + assertEquals(RefUpdate.Result.REJECTED, + res.getTrackingRefUpdate("refs/heads/master").getResult()); + res = git.fetch().setRemote("test") + .setRefSpecs("refs/heads/master:refs/heads/master") + .setForceUpdate(true).call(); + assertEquals(RefUpdate.Result.FORCED, + res.getTrackingRefUpdate("refs/heads/master").getResult()); + } + @Test public void fetchShouldAutoFollowTag() throws Exception { remoteGit.commit().setMessage("commit").call(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java index 5d178bc13..73e93a1c9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/FetchCommand.java @@ -105,6 +105,8 @@ public class FetchCommand extends TransportCommand { private Callback callback; + private boolean isForceUpdate; + /** * Callback for status of fetch operation. * @@ -198,7 +200,8 @@ private void fetchSubmodules(FetchResult results) .setTagOpt(tagOption) .setCheckFetchedObjects(checkFetchedObjects) .setRemoveDeletedRefs(isRemoveDeletedRefs()) - .setThin(thin).setRefSpecs(refSpecs) + .setThin(thin) + .setRefSpecs(applyOptions(refSpecs)) .setDryRun(dryRun) .setRecurseSubmodules(recurseMode); configure(f); @@ -237,8 +240,8 @@ public FetchResult call() throws GitAPIException, InvalidRemoteException, transport.setTagOpt(tagOption); transport.setFetchThin(thin); configure(transport); - - FetchResult result = transport.fetch(monitor, refSpecs); + FetchResult result = transport.fetch(monitor, + applyOptions(refSpecs)); if (!repo.isBare()) { fetchSubmodules(result); } @@ -261,6 +264,17 @@ public FetchResult call() throws GitAPIException, InvalidRemoteException, } + private List applyOptions(List refSpecs2) { + if (!isForceUpdate()) { + return refSpecs2; + } + List updated = new ArrayList<>(3); + for (RefSpec refSpec : refSpecs2) { + updated.add(refSpec.setForceUpdate(true)); + } + return updated; + } + /** * Set the mode to be used for recursing into submodules. * @@ -517,4 +531,27 @@ public FetchCommand setCallback(Callback callback) { this.callback = callback; return this; } + + /** + * Whether fetch --force option is enabled + * + * @return whether refs affected by the fetch are updated forcefully + * @since 5.0 + */ + public boolean isForceUpdate() { + return this.isForceUpdate; + } + + /** + * Set fetch --force option + * + * @param force + * whether to update refs affected by the fetch forcefully + * @return this command + * @since 5.0 + */ + public FetchCommand setForceUpdate(boolean force) { + this.isForceUpdate = force; + return this; + } }