From 5c01e59976b51500c379a36b1494a3854318593f Mon Sep 17 00:00:00 2001 From: JBYoshi Date: Sun, 18 Oct 2015 21:00:07 -0500 Subject: [PATCH 1/2] Work on rebasing --- .../java/jbyoshi/gitupdate/GitUpdate.java | 2 +- .../jbyoshi/gitupdate/processor/Rebase.java | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/main/java/jbyoshi/gitupdate/processor/Rebase.java diff --git a/src/main/java/jbyoshi/gitupdate/GitUpdate.java b/src/main/java/jbyoshi/gitupdate/GitUpdate.java index f07b040..445d3ee 100644 --- a/src/main/java/jbyoshi/gitupdate/GitUpdate.java +++ b/src/main/java/jbyoshi/gitupdate/GitUpdate.java @@ -30,7 +30,7 @@ public class GitUpdate { private static final Set updated = new HashSet(); private static final ImmutableList processors = ImmutableList.of(new Fetch(), new FastForward(), - new Push()); + new Rebase(), new Push()); public static void main(String[] args) { File gitDir = new File(System.getProperty("user.home"), "git"); diff --git a/src/main/java/jbyoshi/gitupdate/processor/Rebase.java b/src/main/java/jbyoshi/gitupdate/processor/Rebase.java new file mode 100644 index 0000000..cf4c5b9 --- /dev/null +++ b/src/main/java/jbyoshi/gitupdate/processor/Rebase.java @@ -0,0 +1,61 @@ +package jbyoshi.gitupdate.processor; + +import java.io.*; + +import org.eclipse.jgit.api.*; +import org.eclipse.jgit.api.errors.*; +import org.eclipse.jgit.lib.*; + +import jbyoshi.gitupdate.*; + +public final class Rebase extends BranchProcessor { + + @Override + public void process(Repository repo, Git git, String branch, Ref ref, Report report) + throws IOException, GitAPIException { + String trackingBranch = new BranchConfig(repo.getConfig(), branch).getTrackingBranch(); + if (trackingBranch == null) { + return; + } + + Ref oldHead = repo.getRef(Constants.HEAD).getTarget(); + if (!oldHead.equals(ref)) { + try { + git.checkout().setName(ref.getName()).setCreateBranch(false).call(); + } catch (RefAlreadyExistsException e) { + throw new AssertionError(e); + } catch (RefNotFoundException e) { + throw new AssertionError(e); + } catch (InvalidRefNameException e) { + throw new AssertionError(e); + } + } + + try { + RebaseResult result = git.rebase().setUpstream(trackingBranch).call(); + switch (result.getStatus()) { + case STOPPED: + case CONFLICTS: + Report conflicts = report.newChild("Conflicts").error(); + result.getConflicts().forEach(file -> conflicts.newChild(file).error()); + git.rebase().setOperation(RebaseCommand.Operation.ABORT).call(); + break; + case UP_TO_DATE: + break; + default: + Report details = report.newChild(result.getStatus().toString()); + if (result.getStatus().isSuccessful()) { + details.modified(); + } else { + details.error(); + } + break; + } + } catch (NoHeadException e) { + throw new AssertionError(e); + } finally { + git.checkout().setName(branch).call(); + } + } + +} From 4c85fefa28a2bd7cb1a053524c7fea2843f9d806 Mon Sep 17 00:00:00 2001 From: JBYoshi Date: Sun, 8 May 2016 16:36:25 -0500 Subject: [PATCH 2/2] Add force pushing to rebased branches. --- .../jbyoshi/gitupdate/processor/Push.java | 76 +++++++++++++++---- .../jbyoshi/gitupdate/processor/Rebase.java | 3 + 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/main/java/jbyoshi/gitupdate/processor/Push.java b/src/main/java/jbyoshi/gitupdate/processor/Push.java index 5fe083d..f4af710 100644 --- a/src/main/java/jbyoshi/gitupdate/processor/Push.java +++ b/src/main/java/jbyoshi/gitupdate/processor/Push.java @@ -15,9 +15,19 @@ */ package jbyoshi.gitupdate.processor; +import java.io.IOException; +import java.net.URISyntaxException; +import java.text.MessageFormat; import java.util.*; +import java.util.stream.Collectors; import org.eclipse.jgit.api.*; +import org.eclipse.jgit.api.errors.InvalidRemoteException; +import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.errors.NotSupportedException; +import org.eclipse.jgit.errors.TooLargePackException; +import org.eclipse.jgit.errors.TransportException; +import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.lib.*; import org.eclipse.jgit.transport.*; @@ -26,6 +36,12 @@ import jbyoshi.gitupdate.*; public final class Push extends Processor { + private static final Map> forcePushBranches = new WeakHashMap<>(); + + static void forcePush(Repository repo, String branch) { + if (branch.startsWith(Constants.R_HEADS)) branch = branch.substring(Constants.R_HEADS.length()); + forcePushBranches.computeIfAbsent(repo, k -> new HashSet<>()).add(branch); + } @Override public void registerTasks(Repository repo, Git git, Task root) throws Exception { @@ -41,7 +57,7 @@ public void registerTasks(Repository repo, Git git, Task root) throws Exception for (Map.Entry> remote : branchList.asMap().entrySet()) { me.newChild(remote.getKey(), report -> { try { - process(repo, git, remote.getKey(), remote.getValue(), report); + process(repo, remote.getKey(), remote.getValue(), report); } catch (Exception e) { report.newErrorChild(e); } @@ -49,7 +65,7 @@ public void registerTasks(Repository repo, Git git, Task root) throws Exception } } - private static void process(Repository repo, Git git, String remote, Collection branches, + private static void process(Repository repo, String remote, Collection branches, Report report) throws Exception { // Figure out if anything needs to be pushed. Map oldIds = new HashMap<>(); @@ -69,21 +85,55 @@ private static void process(Repository repo, Git git, String remote, Collection< return; } - PushCommand push = git.push().setCredentialsProvider(Prompts.INSTANCE).setTimeout(5) - .setRemote(remote); + ArrayList refSpecs = new ArrayList<>(); for (String branch : branches) { - push.add(Constants.R_HEADS + branch); + RefSpec spec = new RefSpec(Constants.R_HEADS + branch); + refSpecs.add(spec); } - for (PushResult result : push.call()) { - for (RemoteRefUpdate update : result.getRemoteUpdates()) { - if (update.getStatus() == RemoteRefUpdate.Status.OK) { - String branchName = Utils.getShortBranch(update.getSrcRef()); - ObjectId oldId = oldIds.get(branchName); - String old = oldId.equals(ObjectId.zeroId()) ? "new branch" : oldId.name(); - report.newChild(branchName + ": " + old + " -> " + update.getNewObjectId().name()) - .modified(); + + try { + final List transports; + transports = Transport.openAll(repo, remote, Transport.Operation.PUSH); + for (final Transport transport : transports) { + transport.setCredentialsProvider(Prompts.INSTANCE); + + List fetchRefSpecs = new RemoteConfig(repo.getConfig(), remote).getFetchRefSpecs(); + final List toPush = new ArrayList<>( + Transport.findRemoteRefUpdatesFor(repo, refSpecs, fetchRefSpecs)); + for (int i = 0; i < toPush.size(); i++) { + final RemoteRefUpdate update = toPush.get(i); + if (update.isForceUpdate()) { + toPush.set(i, new RemoteRefUpdate(update, repo.resolve( + update.getTrackingRefUpdate().getLocalName()))); + } + } + + try { + PushResult result = transport.push(null, toPush, null); + + for (RemoteRefUpdate update : result.getRemoteUpdates()) { + if (update.getStatus() == RemoteRefUpdate.Status.OK) { + String branchName = Utils.getShortBranch(update.getSrcRef()); + ObjectId oldId = oldIds.get(branchName); + String old = oldId.equals(ObjectId.zeroId()) ? "new branch" : oldId.name(); + report.newChild(branchName + ": " + old + " -> " + update.getNewObjectId().name()) + .modified(); + } + } + } catch (TooLargePackException e) { + throw new org.eclipse.jgit.api.errors.TooLargePackException(e.getMessage(), e); + } catch (TransportException e) { + throw new org.eclipse.jgit.api.errors.TransportException(e.getMessage(), e); + } finally { + transport.close(); } } + } catch (URISyntaxException e) { + throw new InvalidRemoteException(MessageFormat.format(JGitText.get().invalidRemote, remote)); + } catch (TransportException e) { + throw new org.eclipse.jgit.api.errors.TransportException(e.getMessage(), e); + } catch (IOException e) { + throw new JGitInternalException(JGitText.get().exceptionCaughtDuringExecutionOfPushCommand,e); } } diff --git a/src/main/java/jbyoshi/gitupdate/processor/Rebase.java b/src/main/java/jbyoshi/gitupdate/processor/Rebase.java index cf4c5b9..1a6eee8 100644 --- a/src/main/java/jbyoshi/gitupdate/processor/Rebase.java +++ b/src/main/java/jbyoshi/gitupdate/processor/Rebase.java @@ -42,6 +42,9 @@ public void process(Repository repo, Git git, String branch, Ref ref, Report rep break; case UP_TO_DATE: break; + case OK: + Push.forcePush(repo, branch); + //$FALL-THROUGH$ default: Report details = report.newChild(result.getStatus().toString()); if (result.getStatus().isSuccessful()) {