/** * 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; }
public static void getLocalCommittedChanges( final Project project, final VirtualFile root, final Consumer<GitSimpleHandler> parametersSpecifier, final Consumer<GitCommittedChangeList> consumer, boolean skipDiffsForMerge) throws VcsException { GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG); h.setSilent(true); h.addParameters( "--pretty=format:%x04%x01" + GitChangeUtils.COMMITTED_CHANGELIST_FORMAT, "--name-status"); parametersSpecifier.consume(h); String output = h.run(); LOG.debug("getLocalCommittedChanges output: '" + output + "'"); StringScanner s = new StringScanner(output); final StringBuilder sb = new StringBuilder(); boolean firstStep = true; while (s.hasMoreData()) { final String line = s.line(); final boolean lineIsAStart = line.startsWith("\u0004\u0001"); if ((!firstStep) && lineIsAStart) { final StringScanner innerScanner = new StringScanner(sb.toString()); sb.setLength(0); consumer.consume( GitChangeUtils.parseChangeList( project, root, innerScanner, skipDiffsForMerge, h, false, false)); } sb.append(lineIsAStart ? line.substring(2) : line).append('\n'); firstStep = false; } if (sb.length() > 0) { final StringScanner innerScanner = new StringScanner(sb.toString()); sb.setLength(0); consumer.consume( GitChangeUtils.parseChangeList( project, root, innerScanner, skipDiffsForMerge, h, false, false)); } if (s.hasMoreData()) { throw new IllegalStateException("More input is avaialble: " + s.line()); } }
/** * Scan working tree and detect locally modified files * * @param project the project to scan * @param root the root to scan * @param files the collection with files * @throws VcsException if there problem with running git or working tree is dirty in unsupported * way */ private static void scanFiles(Project project, VirtualFile root, List<String> files) throws VcsException { String rootPath = root.getPath(); GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.DIFF); h.addParameters("--name-status"); h.setNoSSH(true); h.setSilent(true); h.setStdoutSuppressed(true); StringScanner s = new StringScanner(h.run()); while (s.hasMoreData()) { if (s.isEol()) { s.line(); continue; } if (s.tryConsume("M\t")) { String path = rootPath + "/" + GitUtil.unescapePath(s.line()); files.add(path); } else { throw new VcsException("Working tree is dirty in unsupported way: " + s.line()); } } }
/** * Parse changes from lines * * @param root the git root * @return a set of unmerged files * @throws com.intellij.openapi.vcs.VcsException if the input format does not matches expected * format */ private List<VirtualFile> unmergedFiles(final VirtualFile root) throws VcsException { GitRepository repository = myRepositoryManager.getRepositoryForRoot(root); if (repository == null) { LOG.error("Repository not found for root " + root); return Collections.emptyList(); } GitCommandResult result = myGit.getUnmergedFiles(repository); if (!result.success()) { throw new VcsException(result.getErrorOutputAsJoinedString()); } String output = StringUtil.join(result.getOutput(), "\n"); HashSet<String> unmergedPaths = ContainerUtil.newHashSet(); for (StringScanner s = new StringScanner(output); s.hasMoreData(); ) { if (s.isEol()) { s.nextLine(); continue; } s.boundedToken('\t'); String relative = s.line(); unmergedPaths.add(GitUtil.unescapePath(relative)); } if (unmergedPaths.size() == 0) { return Collections.emptyList(); } else { List<File> files = ContainerUtil.map( unmergedPaths, new Function<String, File>() { @Override public File fun(String path) { return new File(root.getPath(), path); } }); return sortVirtualFilesByPresentation(findVirtualFilesWithRefresh(files)); } }