/** * Returns absolute paths which have changed remotely comparing to the current branch, i.e. * performs <code>git diff --name-only master..origin/master</code> * * <p>Paths are absolute, Git-formatted (i.e. with forward slashes). */ @NotNull public static Collection<String> getPathsDiffBetweenRefs( @NotNull Git git, @NotNull GitRepository repository, @NotNull String beforeRef, @NotNull String afterRef) throws VcsException { List<String> parameters = Arrays.asList("--name-only", "--pretty=format:"); String range = beforeRef + ".." + afterRef; GitCommandResult result = git.diff(repository, parameters, range); if (!result.success()) { LOG.info( String.format( "Couldn't get diff in range [%s] for repository [%s]", range, repository.toLogString())); return Collections.emptyList(); } final Collection<String> remoteChanges = new HashSet<String>(); for (StringScanner s = new StringScanner(result.getOutputAsJoinedString()); s.hasMoreData(); ) { final String relative = s.line(); if (StringUtil.isEmptyOrSpaces(relative)) { continue; } final String path = repository.getRoot().getPath() + "/" + unescapePath(relative); remoteChanges.add(path); } return remoteChanges; }
@NotNull public static Collection<GitRepository> getRepositoriesFromRoots( @NotNull GitRepositoryManager repositoryManager, @NotNull Collection<VirtualFile> roots) { Collection<GitRepository> repositories = new ArrayList<GitRepository>(roots.size()); for (VirtualFile root : roots) { GitRepository repo = repositoryManager.getRepositoryForRoot(root); if (repo == null) { LOG.error("Repository not found for root " + root); } else { repositories.add(repo); } } return repositories; }
@Override public void run(@NotNull ProgressIndicator indicator) { final List<Root> emptyRoots = loadRoots( myProject, myVcsRoots, myExceptions, false); // collect roots without fetching - just to show dialog if (!myExceptions.isEmpty()) { myExceptions.addAll(myExceptions); return; } myDialog = new GitPushActiveBranchesDialog(myProject, myVcsRoots, emptyRoots); myDialog.refreshTree(true, null, false); // start initial fetch indicator .stop(); // if indicator is not stopped, the progress would be displayed all the time the // dialog is displayed. }
private static String parseRefs( SymbolicRefsI refs, Collection<String> currentRefs, List<String> locals, List<String> remotes, List<String> tags) { if (refs == null) return null; for (String ref : currentRefs) { final SymbolicRefs.Kind kind = refs.getKind(ref); if (SymbolicRefs.Kind.LOCAL.equals(kind)) { locals.add(ref); } else if (SymbolicRefs.Kind.REMOTE.equals(kind)) { remotes.add(ref); } else { tags.add(ref); } } if (refs.getCurrent() != null && currentRefs.contains(refs.getCurrent().getName())) return refs.getCurrent().getName(); return null; }
public static void historyWithLinks( final Project project, FilePath path, @Nullable final SymbolicRefsI refs, @NotNull final AsynchConsumer<GitCommit> gitCommitConsumer, @Nullable final Getter<Boolean> isCanceled, @Nullable Collection<VirtualFile> paths, final String... parameters) throws VcsException { // adjust path using change manager path = getLastCommitName(project, path); final VirtualFile root = GitUtil.getGitRoot(path); final GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG); final GitLogParser parser = new GitLogParser( project, GitLogParser.NameStatus.STATUS, SHORT_HASH, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL, COMMITTER_NAME, COMMITTER_EMAIL, SHORT_PARENTS, REF_NAMES, SUBJECT, BODY, RAW_BODY); h.setNoSSH(true); h.setStdoutSuppressed(true); h.addParameters(parameters); h.addParameters("--name-status", parser.getPretty(), "--encoding=UTF-8", "--full-history"); if (paths != null && !paths.isEmpty()) { h.endOptions(); h.addRelativeFiles(paths); } else { h.addParameters("--sparse"); h.endOptions(); h.addRelativePaths(path); } final VcsException[] exc = new VcsException[1]; final Semaphore semaphore = new Semaphore(); final StringBuilder sb = new StringBuilder(); final Ref<Boolean> skipFirst = new Ref<Boolean>(true); h.addLineListener( new GitLineHandlerAdapter() { @Override public void onLineAvailable(final String line, final Key outputType) { try { if (ProcessOutputTypes.STDOUT.equals(outputType)) { if (isCanceled != null && isCanceled.get()) { h.cancel(); return; } // if (line.charAt(line.length() - 1) != '\u0003') { if ((!line.startsWith("\u0001")) || skipFirst.get()) { if (sb.length() > 0) { sb.append("\n"); } sb.append(line); skipFirst.set(false); return; } takeLine(project, line, sb, parser, refs, root, exc, h, gitCommitConsumer); } } catch (ProcessCanceledException e) { h.cancel(); semaphore.up(); } } @Override public void processTerminated(int exitCode) { semaphore.up(); } @Override public void startFailed(Throwable exception) { semaphore.up(); } }); semaphore.down(); h.start(); semaphore.waitFor(); takeLine(project, "", sb, parser, refs, root, exc, h, gitCommitConsumer); gitCommitConsumer.finished(); if (exc[0] != null) { throw exc[0]; } }
public static void hashesWithParents( Project project, FilePath path, final AsynchConsumer<CommitHashPlusParents> consumer, final Getter<Boolean> isCanceled, Collection<VirtualFile> paths, final String... parameters) throws VcsException { // adjust path using change manager path = getLastCommitName(project, path); final VirtualFile root = GitUtil.getGitRoot(path); final GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG); final GitLogParser parser = new GitLogParser( project, GitLogParser.NameStatus.NAME, SHORT_HASH, COMMIT_TIME, SHORT_PARENTS, AUTHOR_NAME); h.setNoSSH(true); h.setStdoutSuppressed(true); h.addParameters(parameters); h.addParameters(parser.getPretty(), "--encoding=UTF-8", "--full-history"); if (paths != null && !paths.isEmpty()) { h.endOptions(); h.addRelativeFiles(paths); } else { h.addParameters("--sparse"); h.endOptions(); h.addRelativePaths(path); } final Semaphore semaphore = new Semaphore(); h.addLineListener( new GitLineHandlerListener() { @Override public void onLineAvailable(final String line, final Key outputType) { try { if (ProcessOutputTypes.STDOUT.equals(outputType)) { if (isCanceled != null && isCanceled.get()) { h.cancel(); return; } GitLogRecord record = parser.parseOneRecord(line); consumer.consume( new CommitHashPlusParents( record.getShortHash(), record.getParentsShortHashes(), record.getLongTimeStamp() * 1000, record.getAuthorName())); } } catch (ProcessCanceledException e) { h.cancel(); semaphore.up(); } } @Override public void processTerminated(int exitCode) { semaphore.up(); } @Override public void startFailed(Throwable exception) { semaphore.up(); } }); semaphore.down(); h.start(); semaphore.waitFor(); consumer.finished(); }
/** * Load VCS roots * * @param project the project * @param roots the VCS root list * @param exceptions the list of of exceptions to use * @param fetchData if true, the data for remote is fetched. * @return the loaded information about vcs roots */ private static List<Root> loadRoots( final Project project, final List<VirtualFile> roots, final Collection<VcsException> exceptions, final boolean fetchData) { final ArrayList<Root> rc = new ArrayList<Root>(); for (VirtualFile root : roots) { try { Root r = new Root(); rc.add(r); r.root = root; GitBranch b = GitBranch.current(project, root); if (b != null) { r.currentBranch = b.getFullName(); r.remoteName = b.getTrackedRemoteName(project, root); r.remoteBranch = b.getTrackedBranchName(project, root); if (r.remoteName != null) { if (fetchData && !r.remoteName.equals(".")) { GitLineHandler fetch = new GitLineHandler(project, root, GitCommand.FETCH); fetch.addParameters(r.remoteName, "-v"); Collection<VcsException> exs = GitHandlerUtil.doSynchronouslyWithExceptions(fetch); exceptions.addAll(exs); } GitBranch tracked = b.tracked(project, root); assert tracked != null : "Tracked branch cannot be null here"; final boolean trackedBranchExists = tracked.exists(root); if (!trackedBranchExists) { LOG.info("loadRoots tracked branch " + tracked + " doesn't exist yet"); } // check what remote commits are not yet merged if (trackedBranchExists) { GitSimpleHandler toPull = new GitSimpleHandler(project, root, GitCommand.LOG); toPull.addParameters( "--pretty=format:%H", r.currentBranch + ".." + tracked.getFullName()); toPull.setNoSSH(true); toPull.setStdoutSuppressed(true); StringScanner su = new StringScanner(toPull.run()); while (su.hasMoreData()) { if (su.line().trim().length() != 0) { r.remoteCommits++; } } } // check what local commits are to be pushed GitSimpleHandler toPush = new GitSimpleHandler(project, root, GitCommand.LOG); // if the tracked branch doesn't exist yet (nobody pushed the branch yet), show all // commits on this branch. final String revisions = trackedBranchExists ? tracked.getFullName() + ".." + r.currentBranch : r.currentBranch; toPush.addParameters("--pretty=format:%H%x20%ct%x20%at%x20%s%n%P", revisions); toPush.setNoSSH(true); toPush.setStdoutSuppressed(true); StringScanner sp = new StringScanner(toPush.run()); while (sp.hasMoreData()) { if (sp.isEol()) { sp.line(); continue; } Commit c = new Commit(); c.root = r; String hash = sp.spaceToken(); String time = sp.spaceToken(); c.revision = new GitRevisionNumber(hash, new Date(Long.parseLong(time) * 1000L)); c.authorTime = sp.spaceToken(); c.message = sp.line(); c.isMerge = sp.line().indexOf(' ') != -1; r.commits.add(c); } } } } catch (VcsException e) { exceptions.add(e); } } return rc; }