/** {@inheritDoc} */
 @Override
 public Object getValueAt(int rowIndex, int columnIndex) {
   BranchDescriptor d = myBranches.get(rowIndex);
   switch (columnIndex) {
     case ROOT_COLUMN:
       return Pair.create(d.getRoot(), d.root != null);
     case REVISION_COLUMN:
       return Pair.create(d.referenceToCheckout, d.isReferenceValid);
     case NEW_BRANCH_COLUMN:
       return Pair.create(d.newBranchName == null ? "" : d.newBranchName, d.isNewBranchValid);
     case STATUS_COLUMN:
       switch (d.status) {
         case INVALID_BRANCH_NAME:
           return Pair.create("Invalid new branch name", false);
         case BAD_REVISION:
           return Pair.create("Invalid revision", false);
         case MISSING_REVISION:
           return Pair.create("Missing revision", false);
         case CHECKOUT_NEEDED:
           return Pair.create("Checkout", true);
         case REMOVED_ROOT:
           return Pair.create("Removed root", true);
         case NO_ACTION:
           return Pair.create("", true);
         case BRANCH_NAME_EXISTS:
           return Pair.create("Branch name exists", false);
         default:
           throw new IllegalStateException("Unknown status:" + d.status);
       }
     default:
       throw new IllegalStateException("Unknown column: " + columnIndex);
   }
 }
 /** {@inheritDoc} */
 @Override
 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
   String t = (String) aValue;
   BranchDescriptor d = myBranches.get(rowIndex);
   if (d.root == null) {
     return;
   }
   if (columnIndex == REVISION_COLUMN) {
     String currentCandidate = getCandidateLocal(d.referenceToCheckout, d);
     boolean isCurrentMatchCandidate =
         currentCandidate != null && currentCandidate.equals(d.newBranchName);
     d.referenceToCheckout = t;
     if ((StringUtil.isEmpty(d.newBranchName) || isCurrentMatchCandidate)
         && t.startsWith(REMOTES_PREFIX)
         && d.referencesToSelect.contains(t)) {
       String candidate = getCandidateLocal(t, d);
       if (candidate != null) {
         d.newBranchName = candidate;
       }
     }
   } else if (columnIndex == NEW_BRANCH_COLUMN) {
     d.newBranchName = t;
   }
   d.updateStatus();
   fireTableRowsUpdated(rowIndex, rowIndex);
 }
 /** Verify dialog state */
 private void verify() {
   String text = myNameTextField.getText().trim();
   if (text.length() == 0) {
     setError("Empty configuration name is not allowed.");
     return;
   } else if (myTarget != null && text.equals(myTarget.getName())) {
   } else if (myExistingConfigNames.contains(text)) {
     setError("There is another configuration with the same name");
     return;
   }
   for (BranchDescriptor d : myBranches) {
     switch (d.status) {
       case BRANCH_NAME_EXISTS:
         setError("Duplicate branch name for root " + d.getRoot());
         return;
       case INVALID_BRANCH_NAME:
         setError("Invalid branch name for root " + d.getRoot());
         return;
       case BAD_REVISION:
         setError("Invalid revision for root " + d.getRoot());
         return;
       case MISSING_REVISION:
         setError("The revision must be specified for root " + d.getRoot());
         return;
       case CHECKOUT_NEEDED:
       case NO_ACTION:
       case REMOVED_ROOT:
         break;
       default:
         throw new RuntimeException("Unexpected status: " + d.status);
     }
   }
   setError(null);
 }
 /**
  * Prepare branches for the case of remote checkout
  *
  * @param remoteBranch the remote branch to checkout
  * @param roots the collection of vcs roots
  * @return the list of descriptors for the remote
  * @throws VcsException if failed
  */
 private List<BranchDescriptor> prepareBranchesForRemote(
     String remoteBranch, List<VirtualFile> roots) throws VcsException {
   assert roots.size() > 0;
   List<BranchDescriptor> rc = new ArrayList<BranchDescriptor>();
   HashSet<String> allBranches = new HashSet<String>();
   allBranches.addAll(myConfig.getConfigurationNames());
   final String qualifiedBranch = "remotes/" + remoteBranch;
   String firstRemote = remoteBranch.endsWith("/HEAD") ? null : qualifiedBranch;
   for (VirtualFile root : roots) {
     BranchDescriptor d = new BranchDescriptor();
     d.root = root;
     d.currentReference = myConfig.describeRoot(root);
     if (firstRemote == null) {
       firstRemote = resolveHead(qualifiedBranch, d.root.getPath());
     }
     d.referenceToCheckout = qualifiedBranch;
     Branch.listAsStrings(myProject, root, false, true, d.existingBranches, null);
     Branch.listAsStrings(myProject, root, true, true, d.referencesToSelect, null);
     allBranches.addAll(d.existingBranches);
     rc.add(d);
   }
   String candidate;
   if (firstRemote == null) {
     candidate = "untitled";
   } else {
     int p = firstRemote.indexOf('/', REMOTES_PREFIX.length() + 1);
     assert p > 0 && p < firstRemote.length() - 1
         : "Unexpected format for remote branch: " + firstRemote;
     candidate = firstRemote.substring(p + 1);
   }
   String actual = null;
   if (!allBranches.contains(candidate)) {
     actual = candidate;
   } else {
     for (int i = 2; i < Integer.MAX_VALUE; i++) {
       String t = candidate + i;
       if (!allBranches.contains(t)) {
         actual = t;
         break;
       }
     }
     assert actual != null : "Unexpected number of branches: " + remoteBranch;
   }
   for (BranchDescriptor d : rc) {
     d.newBranchName = actual;
     d.updateStatus();
   }
   return rc;
 }
 /**
  * Prepare branch descriptors for existing configuration
  *
  * @param target the target
  * @param roots the vcs root
  * @return the list of branch descriptors
  * @throws VcsException in case of error
  */
 private List<BranchDescriptor> prepareBranchDescriptors(
     BranchConfiguration target, List<VirtualFile> roots) throws VcsException {
   Map<String, String> map =
       target == null ? Collections.<String, String>emptyMap() : target.getReferences();
   List<BranchDescriptor> rc = new ArrayList<BranchDescriptor>();
   for (VirtualFile root : roots) {
     BranchDescriptor d = new BranchDescriptor();
     d.root = root;
     d.storedReference = map.remove(root.getPath());
     if (d.storedReference != null) {
       d.storedRoot = d.root.getPath();
     }
     d.currentReference = myConfig.describeRoot(root);
     if (d.storedReference != null && !myModify) {
       d.referenceToCheckout = d.storedReference;
     } else {
       d.referenceToCheckout = d.currentReference;
     }
     Branch.listAsStrings(myProject, root, false, true, d.existingBranches, null);
     Branch.listAsStrings(myProject, root, true, true, d.referencesToSelect, null);
     d.updateStatus();
     rc.add(d);
   }
   for (Map.Entry<String, String> m : map.entrySet()) {
     String root = m.getKey();
     String ref = m.getValue();
     BranchDescriptor d = new BranchDescriptor();
     d.storedReference = ref;
     d.storedRoot = root;
     d.referenceToCheckout = ref;
     d.updateStatus();
     rc.add(d);
   }
   return rc;
 }