Implement --force option in FetchCommand and CLI fetch command

Change-Id: I42cdb57b8fb54ce466d1958391f12f911045327f
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
This commit is contained in:
Matthias Sohn 2018-03-13 02:20:29 +01:00
parent 6f82de449f
commit e23b09ad6e
5 changed files with 79 additions and 3 deletions

View File

@ -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");

View File

@ -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]

View File

@ -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()

View File

@ -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();

View File

@ -105,6 +105,8 @@ public class FetchCommand extends TransportCommand<FetchCommand, FetchResult> {
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<RefSpec> applyOptions(List<RefSpec> refSpecs2) {
if (!isForceUpdate()) {
return refSpecs2;
}
List<RefSpec> 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;
}
}