/** * Update the tree according to the list of loaded roots * * @param roots the list of roots to add to the tree * @param uncheckedCommits the map from vcs root to commit identifiers that should be * uncheckedCommits */ private void updateTree(List<Root> roots, Map<VirtualFile, Set<String>> uncheckedCommits) { myTreeRoot.removeAllChildren(); if (roots == null) { roots = Collections.emptyList(); } for (Root r : roots) { CheckedTreeNode rootNode = new CheckedTreeNode(r); Status status = new Status(); status.root = r; rootNode.add(new DefaultMutableTreeNode(status, false)); Set<String> unchecked = uncheckedCommits != null && uncheckedCommits.containsKey(r.root) ? uncheckedCommits.get(r.root) : Collections.<String>emptySet(); for (Commit c : r.commits) { CheckedTreeNode child = new CheckedTreeNode(c); rootNode.add(child); child.setChecked(r.remoteName != null && !unchecked.contains(c.commitId())); } myTreeRoot.add(rootNode); } }
/** * 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; }
private RebaseInfo collectRebaseInfo() { final Set<VirtualFile> roots = new HashSet<VirtualFile>(); final Set<VirtualFile> rootsWithMerges = new HashSet<VirtualFile>(); final Map<VirtualFile, List<String>> reorderedCommits = new HashMap<VirtualFile, List<String>>(); final Map<VirtualFile, Set<String>> uncheckedCommits = new HashMap<VirtualFile, Set<String>>(); for (int i = 0; i < myTreeRoot.getChildCount(); i++) { CheckedTreeNode node = (CheckedTreeNode) myTreeRoot.getChildAt(i); Root r = (Root) node.getUserObject(); Set<String> unchecked = new HashSet<String>(); uncheckedCommits.put(r.root, unchecked); if (r.commits.size() == 0) { if (r.remoteCommits > 0) { roots.add(r.root); } continue; } boolean seenCheckedNode = false; boolean reorderNeeded = false; boolean seenMerges = false; for (int j = 0; j < node.getChildCount(); j++) { if (node.getChildAt(j) instanceof CheckedTreeNode) { CheckedTreeNode commitNode = (CheckedTreeNode) node.getChildAt(j); Commit commit = (Commit) commitNode.getUserObject(); seenMerges |= commit.isMerge; if (commitNode.isChecked()) { seenCheckedNode = true; } else { unchecked.add(commit.commitId()); if (seenCheckedNode) { reorderNeeded = true; } } } } if (seenMerges) { rootsWithMerges.add(r.root); } if (r.remoteCommits > 0 || reorderNeeded) { roots.add(r.root); } if (reorderNeeded) { List<String> reordered = new ArrayList<String>(); for (int j = 0; j < node.getChildCount(); j++) { if (node.getChildAt(j) instanceof CheckedTreeNode) { CheckedTreeNode commitNode = (CheckedTreeNode) node.getChildAt(j); if (!commitNode.isChecked()) { Commit commit = (Commit) commitNode.getUserObject(); reordered.add(commit.revision.asString()); } } } for (int j = 0; j < node.getChildCount(); j++) { if (node.getChildAt(j) instanceof CheckedTreeNode) { CheckedTreeNode commitNode = (CheckedTreeNode) node.getChildAt(j); if (commitNode.isChecked()) { Commit commit = (Commit) commitNode.getUserObject(); reordered.add(commit.revision.asString()); } } } Collections.reverse(reordered); reorderedCommits.put(r.root, reordered); } } final GitVcsSettings.UpdateChangesPolicy p = UpdatePolicyUtils.getUpdatePolicy(myStashRadioButton, myShelveRadioButton); assert p == GitVcsSettings.UpdateChangesPolicy.STASH || p == GitVcsSettings.UpdateChangesPolicy.SHELVE; return new RebaseInfo(reorderedCommits, rootsWithMerges, uncheckedCommits, roots, p); }