/** * Gets info of the given commit and checks if it was a RENAME. If yes, returns the older file * path, which file was renamed from. If it's not a rename, returns null. */ @Nullable private static FilePath getFirstCommitRenamePath( Project project, VirtualFile root, String commit, FilePath filePath) throws VcsException { // 'git show -M --name-status <commit hash>' returns the information about commit and detects // renames. // NB: we can't specify the filepath, because then rename detection will work only with the // '--follow' option, which we don't wanna use. final GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.SHOW); final GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS, HASH, COMMIT_TIME, SHORT_PARENTS); h.setNoSSH(true); h.setStdoutSuppressed(true); h.addParameters("-M", "--name-status", parser.getPretty(), "--encoding=UTF-8", commit); h.endOptions(); final String output = h.run(); final List<GitLogRecord> records = parser.parse(output); if (records.isEmpty()) return null; // we have information about all changed files of the commit. Extracting information about the // file we need. final List<Change> changes = records.get(0).parseChanges(project, root); for (Change change : changes) { if ((change.isMoved() || change.isRenamed()) && filePath.equals(change.getAfterRevision().getFile())) { return change.getBeforeRevision().getFile(); } } return null; }
/** * Get history for the file * * @param project the context project * @param path the file path * @return the list of the revisions * @throws VcsException if there is problem with running git */ public static List<VcsFileRevision> history( final Project project, FilePath path, final VirtualFile root, final String... parameters) throws VcsException { final List<VcsFileRevision> rc = new ArrayList<VcsFileRevision>(); final List<VcsException> exceptions = new ArrayList<VcsException>(); history( project, path, root, new Consumer<GitFileRevision>() { @Override public void consume(GitFileRevision gitFileRevision) { rc.add(gitFileRevision); } }, new Consumer<VcsException>() { @Override public void consume(VcsException e) { exceptions.add(e); } }, parameters); if (!exceptions.isEmpty()) { throw exceptions.get(0); } return rc; }
/** * Get current revision for the file under git * * @param project a project * @param filePath a file path * @return a revision number or null if the file is unversioned or new * @throws VcsException if there is problem with running git */ @Nullable public static ItemLatestState getLastRevision(final Project project, FilePath filePath) throws VcsException { VirtualFile root = GitUtil.getGitRoot(filePath); GitBranch c = GitBranch.current(project, root); GitBranch t = c == null ? null : c.tracked(project, root); if (t == null) { return new ItemLatestState(getCurrentRevision(project, filePath, null), true, false); } filePath = getLastCommitName(project, filePath); GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG); GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS, HASH, COMMIT_TIME, SHORT_PARENTS); h.setNoSSH(true); h.setSilent(true); h.addParameters("-n1", parser.getPretty(), "--name-status", t.getFullName()); h.endOptions(); h.addRelativePaths(filePath); String result = h.run(); if (result.length() == 0) { return null; } GitLogRecord record = parser.parseOneRecord(result); if (record == null) { return null; } final List<Change> changes = record.parseChanges(project, root); boolean exists = !FileStatus.DELETED.equals(changes.get(0).getFileStatus()); record.setUsedHandler(h); return new ItemLatestState( new GitRevisionNumber(record.getHash(), record.getDate()), exists, false); }
@Nullable public static Pair<AbstractHash, AbstractHash> getStashTop( @NotNull Project project, @NotNull VirtualFile root) throws VcsException { GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.STASH.readLockingCommand()); GitLogParser parser = new GitLogParser(project, SHORT_HASH, SHORT_PARENTS); h.setSilent(true); h.setNoSSH(true); h.addParameters("list"); h.addParameters("-n1"); h.addParameters(parser.getPretty()); String out; h.setCharset(Charset.forName(GitConfigUtil.getLogEncoding(project, root))); out = h.run(); final List<GitLogRecord> gitLogRecords = parser.parse(out); for (GitLogRecord gitLogRecord : gitLogRecords) { ProgressManager.checkCanceled(); GitSimpleHandler h1 = new GitSimpleHandler(project, root, GitCommand.LOG); GitLogParser parser1 = new GitLogParser(project, SHORT_HASH, SHORT_PARENTS, SUBJECT); h1.setSilent(true); h1.setNoSSH(true); h1.addParameters("-n1"); h1.addParameters(parser1.getPretty()); // h1.endOptions(); h1.addParameters(gitLogRecord.getShortHash()); String out1; out1 = h1.run(); final List<GitLogRecord> gitLogRecords1 = parser1.parse(out1); assert gitLogRecords1.size() == 1; final GitLogRecord logRecord = gitLogRecords1.get(0); final String[] parentsShortHashes = logRecord.getParentsShortHashes(); String indexCommit = null; // heuristics if (parentsShortHashes.length == 2) { if (logRecord.getSubject().contains(parentsShortHashes[0])) { indexCommit = parentsShortHashes[1]; } if (logRecord.getSubject().contains(parentsShortHashes[1])) { indexCommit = parentsShortHashes[0]; } } return new Pair<AbstractHash, AbstractHash>( AbstractHash.create(gitLogRecord.getShortHash()), indexCommit == null ? null : AbstractHash.create(indexCommit)); } return null; }