use of org.zmlx.hg4idea.execution.HgCommandResult in project intellij-community by JetBrains.
the class HgMergeProvider method loadRevisions.
@NotNull
@Override
public MergeData loadRevisions(@NotNull final VirtualFile file) throws VcsException {
final MergeData mergeData = new MergeData();
final VcsRunnable runnable = new VcsRunnable() {
@Override
public void run() throws VcsException {
final HgWorkingCopyRevisionsCommand command = new HgWorkingCopyRevisionsCommand(myProject);
final VirtualFile repo = HgUtil.getHgRootOrThrow(myProject, file);
final HgFile hgFile = new HgFile(myProject, file);
HgRevisionNumber serverRevisionNumber;
HgRevisionNumber localRevisionNumber;
HgRevisionNumber baseRevisionNumber = null;
// there are two possibilities: we have checked in local changes in the selected file or we didn't.
if (wasFileCheckedIn(repo, file)) {
// 1. We checked in.
// We have a merge in progress, which means we have 2 heads (parents).
// the second one is "their" revision pulled from the parent repo,
// first parent is the local change.
// to retrieve the base version we get the parent of the local change, i.e. the [only] parent of the first parent.
//Which one is local revision depends on which one is merged with,
// i.e if you update to 17 revision and then merge it with 23, so 17 is your local and 17->parent is your base revision.
// This may produce misunderstanding when you update your project with merging (your update firstly to next revisions and then
// merge with previous). see http://hgbook.red-bean.com/read/managing-releases-and-branchy-development.html
final Couple<HgRevisionNumber> parents = command.parents(repo, file);
serverRevisionNumber = parents.second;
localRevisionNumber = parents.first;
final HgContentRevision local = HgContentRevision.create(myProject, hgFile, localRevisionNumber);
mergeData.CURRENT = local.getContentAsBytes();
// we are sure that we have a common ancestor, because otherwise we'll get "repository is unrelated" error while pulling,
// due to different root changesets which is prohibited.
// Find common ancestor of two revisions : hg debugancestor rev1 rev2
// Using quotes may produce wrong escaping errors on Unix-type systems
List<String> arguments = new ArrayList<>();
String localChangeset = localRevisionNumber.getChangeset();
String serverChangeset = serverRevisionNumber.getChangeset();
arguments.add(StringUtil.isEmptyOrSpaces(localChangeset) ? localRevisionNumber.getRevision() : localChangeset);
arguments.add(StringUtil.isEmptyOrSpaces(serverChangeset) ? serverRevisionNumber.getRevision() : serverChangeset);
HgCommandResult result = new HgPromptCommandExecutor(myProject).executeInCurrentThread(repo, "debugancestor", arguments);
if (result != null) {
String output = result.getRawOutput();
final List<String> parts = StringUtil.split(output, ":");
if (parts.size() < 2) {
LOG.info("Couldn't parse result of debugancestor command execution " + arguments);
new HgCommandResultNotifier(myProject).notifyError(null, HgVcsMessages.message("hg4idea.error.debugancestor.command.execution"), HgVcsMessages.message("hg4idea.error.debugancestor.command.description"));
} else {
baseRevisionNumber = HgRevisionNumber.getInstance(parts.get(0), parts.get(1));
}
} else {
LOG.info(HgVcsMessages.message("hg4idea.error.debugancestor.command.execution") + arguments);
new HgCommandResultNotifier(myProject).notifyError(null, HgVcsMessages.message("hg4idea.error.debugancestor.command.execution"), HgVcsMessages.message("hg4idea.error.debugancestor.command.description"));
}
} else {
// 2. local changes are not checked in.
// then there is only one parent, which is server changes.
// local changes are retrieved from the file system, they are not in the Mercurial yet.
// base is the only parent of server changes.
serverRevisionNumber = command.parents(repo, file).first;
baseRevisionNumber = command.parents(repo, file, serverRevisionNumber).first;
final File origFile = new File(file.getPath() + ".orig");
mergeData.CURRENT = VcsUtil.getFileByteContent(origFile);
}
if (baseRevisionNumber != null) {
final HgContentRevision base = HgContentRevision.create(myProject, hgFile, baseRevisionNumber);
//if file doesn't exist in ancestor revision the base revision should be empty
mergeData.ORIGINAL = base.getContent() != null ? base.getContentAsBytes() : ArrayUtil.EMPTY_BYTE_ARRAY;
} else {
// no base revision means that the file was added simultaneously with different content in both repositories
mergeData.ORIGINAL = ArrayUtil.EMPTY_BYTE_ARRAY;
}
final HgContentRevision server = HgContentRevision.create(myProject, hgFile, serverRevisionNumber);
mergeData.LAST = server.getContentAsBytes();
file.refresh(false, false);
}
};
VcsUtil.runVcsProcessWithProgress(runnable, VcsBundle.message("multiple.file.merge.loading.progress.title"), false, myProject);
return mergeData;
}
use of org.zmlx.hg4idea.execution.HgCommandResult in project intellij-community by JetBrains.
the class HgStatusCommand method executeInCurrentThread.
public Set<HgChange> executeInCurrentThread(VirtualFile repo, @Nullable Collection<FilePath> paths) {
if (repo == null) {
return Collections.emptySet();
}
HgCommandExecutor executor = new HgCommandExecutor(myProject);
executor.setSilent(true);
List<String> options = new LinkedList<>();
if (myIncludeAdded) {
options.add("--added");
}
if (myIncludeModified) {
options.add("--modified");
}
if (myIncludeRemoved) {
options.add("--removed");
}
if (myIncludeDeleted) {
options.add("--deleted");
}
if (myIncludeUnknown) {
options.add("--unknown");
}
if (myIncludeIgnored) {
options.add("--ignored");
}
if (myIncludeCopySource) {
options.add("--copies");
}
if (myCleanStatus) {
options.add("--clean");
}
executor.setOutputAlwaysSuppressed(myCleanStatus || myIncludeUnknown || myIncludeIgnored);
if (myBaseRevision != null && (!myBaseRevision.getRevision().isEmpty() || !myBaseRevision.getChangeset().isEmpty())) {
options.add("--rev");
options.add(StringUtil.isEmptyOrSpaces(myBaseRevision.getChangeset()) ? myBaseRevision.getRevision() : myBaseRevision.getChangeset());
if (myTargetRevision != null) {
options.add("--rev");
options.add(myTargetRevision.getChangeset());
}
}
final Set<HgChange> changes = new HashSet<>();
if (paths != null) {
final List<List<String>> chunked = VcsFileUtil.chunkPaths(repo, paths);
for (List<String> chunk : chunked) {
List<String> args = new ArrayList<>();
args.addAll(options);
args.addAll(chunk);
HgCommandResult result = executor.executeInCurrentThread(repo, "status", args);
changes.addAll(parseChangesFromResult(repo, result, args));
}
} else {
HgCommandResult result = executor.executeInCurrentThread(repo, "status", options);
changes.addAll(parseChangesFromResult(repo, result, options));
}
return changes;
}
use of org.zmlx.hg4idea.execution.HgCommandResult in project intellij-community by JetBrains.
the class HgUpdateCommand method updateRepoToInCurrentThread.
public static boolean updateRepoToInCurrentThread(@NotNull final Project project, @NotNull final VirtualFile repository, @NotNull final String targetRevision, final boolean clean) {
final HgUpdateCommand hgUpdateCommand = new HgUpdateCommand(project, repository);
hgUpdateCommand.setRevision(targetRevision);
hgUpdateCommand.setClean(clean);
HgCommandResult result = hgUpdateCommand.execute();
new HgConflictResolver(project).resolve(repository);
boolean success = !HgErrorUtil.isCommandExecutionFailed(result);
boolean hasUnresolvedConflicts = HgConflictResolver.hasConflicts(project, repository);
if (!success) {
new HgCommandResultNotifier(project).notifyError(result, "", "Update failed");
} else if (hasUnresolvedConflicts) {
new VcsNotifier(project).notifyImportantWarning("Unresolved conflicts.", HgVcsMessages.message("hg4idea.update.warning.merge.conflicts", repository.getPath()));
}
getRepositoryManager(project).updateRepository(repository);
HgErrorUtil.markDirtyAndHandleErrors(project, repository);
return success;
}
use of org.zmlx.hg4idea.execution.HgCommandResult in project intellij-community by JetBrains.
the class HgWorkingCopyRevisionsCommand method identify.
/**
* Returns the result of 'hg id' execution, i.e. current state of the repository.
* @return one or two revision numbers. Two revisions is the case of unresolved merge. In other cases there are only one revision.
*/
@NotNull
public Couple<HgRevisionNumber> identify(@NotNull VirtualFile repo) {
HgCommandExecutor commandExecutor = new HgCommandExecutor(myProject);
commandExecutor.setSilent(true);
HgCommandResult result = commandExecutor.executeInCurrentThread(repo, "identify", Arrays.asList("--num", "--id"));
if (result == null) {
return Couple.of(HgRevisionNumber.NULL_REVISION_NUMBER, null);
}
final List<String> lines = result.getOutputLines();
if (lines != null && !lines.isEmpty()) {
List<String> parts = StringUtil.split(lines.get(0), " ");
String changesets = parts.get(0);
String revisions = parts.get(1);
if (parts.size() >= 2) {
if (changesets.indexOf('+') != changesets.lastIndexOf('+')) {
// in the case of unresolved merge we have 2 revisions at once, both current, so with "+"
// 9f2e6c02913c+b311eb4eb004+ 186+183+
List<String> chsets = StringUtil.split(changesets, "+");
List<String> revs = StringUtil.split(revisions, "+");
return Couple.of(HgRevisionNumber.getInstance(revs.get(0) + "+", chsets.get(0) + "+"), HgRevisionNumber.getInstance(revs.get(1) + "+", chsets.get(1) + "+"));
} else {
return Couple.of(HgRevisionNumber.getInstance(revisions, changesets), null);
}
}
}
return Couple.of(HgRevisionNumber.NULL_REVISION_NUMBER, null);
}
use of org.zmlx.hg4idea.execution.HgCommandResult in project intellij-community by JetBrains.
the class HgWorkingCopyRevisionsCommand method getRevisions.
/**
* Returns the list of revisions returned by one mercurial commands (parents, identify, tip).
* Executed a command on the whole repository or on the given file.
* During a merge, the returned list contains 2 revision numbers. The order of these numbers is
* important: the first parent was the parent of the working directory from <em>before</em>
* the merge, the second parent is the changeset that was merged in.
* @param repo repository to execute on.
* @param command command to execute.
* @param file file which revisions are wanted. If <code><b>null</b></code> then repository revisions are considered.
* @param revision revision to execute on. If <code><b>null</b></code> then executed without the '-r' parameter, i.e. on the latest revision.
* @param silent pass true if this command shouldn't be mentioned in the VCS console.
* @return List of revisions.
*/
@NotNull
public List<HgRevisionNumber> getRevisions(@NotNull VirtualFile repo, @NotNull String command, @Nullable FilePath file, @Nullable HgRevisionNumber revision, boolean silent) {
final List<String> args = new LinkedList<>();
args.add("--template");
args.add(HgChangesetUtil.makeTemplate("{rev}", "{node}"));
if (revision != null) {
args.add("-r");
args.add(revision.getChangeset());
}
if (file != null) {
// NB: this must be the last argument
args.add(HgUtil.getOriginalFileName(file, ChangeListManager.getInstance(myProject)).getPath());
}
final HgCommandExecutor executor = new HgCommandExecutor(myProject);
executor.setSilent(silent);
final HgCommandResult result = executor.executeInCurrentThread(repo, command, args);
if (result == null) {
return new ArrayList<>(0);
}
final List<String> lines = new ArrayList<>();
for (String line : result.getRawOutput().split(HgChangesetUtil.CHANGESET_SEPARATOR)) {
if (!line.trim().isEmpty()) {
// filter out empty lines
lines.add(line);
}
}
if (lines.isEmpty()) {
return new ArrayList<>();
}
final List<HgRevisionNumber> revisions = new ArrayList<>(lines.size());
for (String line : lines) {
final List<String> parts = StringUtil.split(line, HgChangesetUtil.ITEM_SEPARATOR);
if (parts.size() < 2) {
LOG.error("getRevisions output parse error in line [" + line + "]\n All lines: \n" + lines);
continue;
}
revisions.add(HgRevisionNumber.getInstance(parts.get(0), parts.get(1)));
}
return revisions;
}
Aggregations