예제 #1
0
  @Test
  public void dontPackHEAD_bare() throws Exception {
    BranchBuilder bb = tr.branch("refs/heads/side");
    bb.commit().add("A", "A").add("B", "B").create();
    RevCommit second = bb.commit().add("A", "A2").add("B", "B2").create();

    // Convert the repo to be bare
    FileBasedConfig cfg = repo.getConfig();
    cfg.setBoolean(
        ConfigConstants.CONFIG_CORE_SECTION, null, ConfigConstants.CONFIG_KEY_BARE, true);
    cfg.save();
    Git git = Git.open(repo.getDirectory());
    repo = (FileRepository) git.getRepository();

    // check for the unborn branch master. HEAD should point to master and
    // master doesn't exist.
    assertEquals(repo.exactRef("HEAD").getTarget().getName(), "refs/heads/master");
    assertNull(repo.exactRef("HEAD").getTarget().getObjectId());
    gc.packRefs();
    assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
    assertEquals(repo.exactRef("HEAD").getTarget().getName(), "refs/heads/master");
    assertNull(repo.exactRef("HEAD").getTarget().getObjectId());

    // check for non-detached HEAD
    repo.updateRef(Constants.HEAD).link("refs/heads/side");
    gc.packRefs();
    assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
    assertEquals(repo.exactRef("HEAD").getTarget().getObjectId(), second.getId());
  }
예제 #2
0
 protected void assertCherryPick(TestRepository<?> testRepo, boolean contentMerge)
     throws IOException {
   assertRebase(testRepo, contentMerge);
   RevCommit remoteHead = getRemoteHead();
   assertThat(remoteHead.getFooterLines("Reviewed-On")).isNotEmpty();
   assertThat(remoteHead.getFooterLines("Reviewed-By")).isNotEmpty();
 }
예제 #3
0
  @Test
  public void dontPackHEAD_nonBare() throws Exception {
    BranchBuilder bb = tr.branch("refs/heads/side");
    RevCommit first = bb.commit().add("A", "A").add("B", "B").create();
    bb.commit().add("A", "A2").add("B", "B2").create();
    Git git = Git.wrap(repo);

    // check for the unborn branch master. HEAD should point to master and
    // master doesn't exist.
    assertEquals(repo.exactRef("HEAD").getTarget().getName(), "refs/heads/master");
    assertNull(repo.exactRef("HEAD").getTarget().getObjectId());
    gc.packRefs();
    assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
    assertEquals(repo.exactRef("HEAD").getTarget().getName(), "refs/heads/master");
    assertNull(repo.exactRef("HEAD").getTarget().getObjectId());

    git.checkout().setName("refs/heads/side").call();
    gc.packRefs();
    assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);

    // check for detached HEAD
    git.checkout().setName(first.getName()).call();
    gc.packRefs();
    assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
  }
 private static Set<String> extractJiraIssues(String pattern, Iterable<RevCommit> commits) {
   HashSet jiraIssues = new LinkedHashSet(); // preserve insertion order
   for (RevCommit commit : commits) {
     jiraIssues.addAll(extractJiraIssuesFromString(commit.getFullMessage(), pattern));
   }
   return jiraIssues;
 }
예제 #5
0
  /**
   * Run consistency checks against the object database.
   *
   * <p>This method completes silently if the checks pass. A temporary revision pool is constructed
   * during the checking.
   *
   * @param tips the tips to start checking from; if not supplied the refs of the repository are
   *     used instead.
   * @throws MissingObjectException
   * @throws IncorrectObjectTypeException
   * @throws IOException
   */
  public void fsck(RevObject... tips)
      throws MissingObjectException, IncorrectObjectTypeException, IOException {
    ObjectWalk ow = new ObjectWalk(db);
    if (tips.length != 0) {
      for (RevObject o : tips) ow.markStart(ow.parseAny(o));
    } else {
      for (Ref r : db.getAllRefs().values()) ow.markStart(ow.parseAny(r.getObjectId()));
    }

    ObjectChecker oc = new ObjectChecker();
    for (; ; ) {
      final RevCommit o = ow.next();
      if (o == null) break;

      final byte[] bin = db.open(o, o.getType()).getCachedBytes();
      oc.checkCommit(bin);
      assertHash(o, bin);
    }

    for (; ; ) {
      final RevObject o = ow.nextObject();
      if (o == null) break;

      final byte[] bin = db.open(o, o.getType()).getCachedBytes();
      oc.check(o.getType(), bin);
      assertHash(o, bin);
    }
  }
예제 #6
0
 @Override
 public String getContent(String objectId, String blobPath) {
   objectId = defaultObjectId(objectId);
   Repository r = git.getRepository();
   RevCommit commit = JGitUtils.getCommit(r, objectId);
   return JGitUtils.getStringContent(r, commit.getTree(), blobPath, encodings);
 }
  @Test
  @Transactional
  @Rollback
  public void testSave() {
    // RecCommit does not mock nicely.
    RevCommit rc = git.add("test", "ABC").commit("test").get();
    FileChanges changes = new FileChanges(repo, rc);
    FileChange fileChange = new FileChange();
    fileChange.setPath("/test/path");
    FileEdits edits = new FileEdits();
    edits.setChangeType(ChangeType.ADD);
    EditList el = new EditList();
    Edit edit = new Edit(10, 10, 10, 20);
    el.add(edit);
    edits.setEdits(el);
    fileChange.addEdit(edits);
    changes.addChange(fileChange);
    repoRepository.save(new Repo(changes.getRepository().getDirectory().getAbsolutePath()));
    fileChangeCallback.filesChanged(changes);

    Commit commit = commitRepository.findOne(rc.getId().getName());
    assertNotNull(commit);
    assertThat(commit.getLinesAdded(), equalTo(10L));
    assertThat(commit.getLinesRemoved(), equalTo(0L));
    assertThat(commit.getFiles().size(), equalTo(1));
  }
예제 #8
0
  @Override
  public PageData getRevisionData(FileSystemPage page, String label) {
    // Workaround for CachingPage
    if (label == null) {
      return persistence.getRevisionData(page, null);
    }
    String content, propertiesXml;
    RevCommit revCommit;
    Repository repository = getRepository(page);

    try {
      String fileSystemPath = getPath(page, repository);
      ObjectId rev = repository.resolve(label);
      RevWalk walk = new RevWalk(repository);
      revCommit = walk.parseCommit(rev);

      content = getRepositoryContent(repository, revCommit, fileSystemPath + "/" + contentFilename);
      propertiesXml =
          getRepositoryContent(repository, revCommit, fileSystemPath + "/" + propertiesFilename);
    } catch (IOException e) {
      throw new RuntimeException("Unable to get data for revision " + label, e);
    }

    final PageData pageData = new PageData(page);
    pageData.setContent(content);
    pageData.setProperties(
        parsePropertiesXml(propertiesXml, revCommit.getAuthorIdent().getWhen().getTime()));
    return pageData;
  }
예제 #9
0
  @Test
  public void testHardResetAfterSquashMerge() throws Exception {
    Git g = new Git(db);

    writeTrashFile("file1", "file1");
    g.add().addFilepattern("file1").call();
    RevCommit first = g.commit().setMessage("initial commit").call();

    assertTrue(resolve(db.getWorkTree(), "file1").exists());
    createBranch(first, "refs/heads/branch1");
    checkoutBranch("refs/heads/branch1");

    writeTrashFile("file2", "file2");
    g.add().addFilepattern("file2").call();
    g.commit().setMessage("second commit").call();
    assertTrue(resolve(db.getWorkTree(), "file2").exists());

    checkoutBranch("refs/heads/master");

    MergeResult result = g.merge().include(db.getRef("branch1")).setSquash(true).call();

    assertEquals(MergeResult.MergeStatus.FAST_FORWARD_SQUASHED, result.getMergeStatus());
    assertNotNull(db.readSquashCommitMsg());

    g.reset().setMode(ResetType.HARD).setRef(first.getName()).call();

    assertNull(db.readSquashCommitMsg());
  }
예제 #10
0
  public CodeReviewCommit createCherryPickFromCommit(
      Repository repo,
      ObjectInserter inserter,
      RevCommit mergeTip,
      RevCommit originalCommit,
      PersonIdent cherryPickCommitterIdent,
      String commitMsg,
      CodeReviewRevWalk rw)
      throws MissingObjectException, IncorrectObjectTypeException, IOException,
          MergeIdenticalTreeException, MergeConflictException {

    final ThreeWayMerger m = newThreeWayMerger(repo, inserter);

    m.setBase(originalCommit.getParent(0));
    if (m.merge(mergeTip, originalCommit)) {
      ObjectId tree = m.getResultTreeId();
      if (tree.equals(mergeTip.getTree())) {
        throw new MergeIdenticalTreeException("identical tree");
      }

      CommitBuilder mergeCommit = new CommitBuilder();
      mergeCommit.setTreeId(tree);
      mergeCommit.setParentId(mergeTip);
      mergeCommit.setAuthor(originalCommit.getAuthorIdent());
      mergeCommit.setCommitter(cherryPickCommitterIdent);
      mergeCommit.setMessage(commitMsg);
      return rw.parseCommit(commit(inserter, mergeCommit));
    } else {
      throw new MergeConflictException("merge conflict");
    }
  }
  // 2. Get branch/commit hash for the source repo - the actual source code
  @Test
  public void existsIn() throws IOException {
    // final String repo = "binrepo-devex";
    //  final String repo = "search_raptor_binary";
    // String githubUrl = "https://github.scm.corp.ebay.com/api/v3";
    // String accessToken = "1cf7d9792235b8592eda18bd7dcc2de37f99b3bc";

    final String path = "D:\\dev\\devex\\binrepo-devex\\.git";

    File gitDir = new File(path);
    org.eclipse.jgit.lib.Repository repository =
        new org.eclipse.jgit.storage.file.FileRepository(gitDir);
    String branch = repository.getBranch();
    System.out.println(branch);

    RevWalk revWalk = new RevWalk(repository);
    // Pop the most recent commit off from RevWalk
    // RevCommit commit = revWalk.next(); returns null :-(
    // System.out.println(commit);

    ObjectId resolve = repository.resolve(Constants.HEAD);
    RevCommit commit = revWalk.parseCommit(resolve);
    String commitHash = commit.getName();
    System.out.println(commitHash + "\t" + commit.getFullMessage());

    // RefDatabase refDatabase = repository.getRefDatabase();

  }
예제 #12
0
 protected String defaultObjectId(Git git, String objectId) {
   if (objectId == null || objectId.trim().length() == 0) {
     RevCommit commit = CommitUtils.getHead(git.getRepository());
     objectId = commit.getName();
   }
   return objectId;
 }
예제 #13
0
  @Test
  public void squash() throws Exception {
    InteractiveHandler messageHandler =
        new InteractiveHandler() {
          public void prepareSteps(List<RebaseTodoLine> steps) {
            // not used
          }

          public String modifyCommitMessage(String commit) {
            return "squashed";
          }
        };

    List<RevCommit> commits = Arrays.asList(commit1, commit2, commit3);
    SquashCommitsOperation op =
        new SquashCommitsOperation(testRepository.getRepository(), commits, messageHandler);
    op.execute(new NullProgressMonitor());

    assertEquals(2, countCommitsInHead());

    LogCommand log = new Git(testRepository.getRepository()).log();
    Iterable<RevCommit> logCommits = log.call();
    RevCommit latestCommit = logCommits.iterator().next();
    assertEquals("squashed", latestCommit.getFullMessage());
  }
예제 #14
0
  @Override
  public List<CommitDB> getCommits() {

    try {

      Iterable<RevCommit> revCommits;
      revCommits = git.log().all().call();
      List<CommitDB> commits = new ArrayList<CommitDB>();

      for (RevCommit revCommit : revCommits) {

        PersonIdent author = revCommit.getAuthorIdent();
        CommitDB commit =
            new CommitDB(0, author.getWhen(), revCommit.getFullMessage(), revCommit.getName());
        CommitterDB committerDb = new CommitterDB(0, author.getEmailAddress(), author.getName());
        commit.setCommitter(committerDb);
        commits.add(commit);
      }

      return commits;

    } catch (GitAPIException e) {
      throw new VisMinerAPIException(e.getMessage(), e);
    } catch (IOException e) {
      throw new VisMinerAPIException(e.getMessage(), e);
    }
  }
예제 #15
0
  @Test
  public void testSomeCommits()
      throws NoHeadException, NoMessageException, UnmergedPathException,
          ConcurrentRefUpdateException, JGitInternalException, WrongRepositoryStateException {

    // do 4 commits
    Git git = new Git(db);
    git.commit().setMessage("initial commit").call();
    git.commit().setMessage("second commit").setCommitter(committer).call();
    git.commit().setMessage("third commit").setAuthor(author).call();
    git.commit().setMessage("fourth commit").setAuthor(author).setCommitter(committer).call();
    Iterable<RevCommit> commits = git.log().call();

    // check that all commits came in correctly
    PersonIdent defaultCommitter = new PersonIdent(db);
    PersonIdent expectedAuthors[] = new PersonIdent[] {defaultCommitter, committer, author, author};
    PersonIdent expectedCommitters[] =
        new PersonIdent[] {defaultCommitter, committer, defaultCommitter, committer};
    String expectedMessages[] =
        new String[] {"initial commit", "second commit", "third commit", "fourth commit"};
    int l = expectedAuthors.length - 1;
    for (RevCommit c : commits) {
      assertEquals(expectedAuthors[l].getName(), c.getAuthorIdent().getName());
      assertEquals(expectedCommitters[l].getName(), c.getCommitterIdent().getName());
      assertEquals(c.getFullMessage(), expectedMessages[l]);
      l--;
    }
    assertEquals(l, -1);
  }
예제 #16
0
  @Test
  public void testAddUnstagedChanges()
      throws IOException, NoHeadException, NoMessageException, ConcurrentRefUpdateException,
          JGitInternalException, WrongRepositoryStateException, NoFilepatternException {
    File file = new File(db.getWorkTree(), "a.txt");
    FileUtils.createNewFile(file);
    PrintWriter writer = new PrintWriter(file);
    writer.print("content");
    writer.close();

    Git git = new Git(db);
    git.add().addFilepattern("a.txt").call();
    RevCommit commit = git.commit().setMessage("initial commit").call();
    TreeWalk tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
    assertEquals("6b584e8ece562ebffc15d38808cd6b98fc3d97ea", tw.getObjectId(0).getName());

    writer = new PrintWriter(file);
    writer.print("content2");
    writer.close();
    commit = git.commit().setMessage("second commit").call();
    tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
    assertEquals("6b584e8ece562ebffc15d38808cd6b98fc3d97ea", tw.getObjectId(0).getName());

    commit = git.commit().setAll(true).setMessage("third commit").setAll(true).call();
    tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
    assertEquals("db00fd65b218578127ea51f3dffac701f12f486a", tw.getObjectId(0).getName());
  }
예제 #17
0
  protected boolean hasIgnoreFile(Repository repository, RevCommit revCommit, String relativePath)
      throws Exception {

    if (_ignoreFileName == null) {
      return false;
    }

    try (TreeWalk treeWalk = new TreeWalk(repository)) {
      treeWalk.addTree(revCommit.getTree());

      if (revCommit.getParentCount() > 0) {
        RevCommit parentRevCommit = revCommit.getParent(0);

        treeWalk.addTree(parentRevCommit.getTree());
      }

      treeWalk.setRecursive(true);

      treeWalk.setFilter(
          AndTreeFilter.create(
              PathFilter.create(relativePath + "/" + _ignoreFileName), TreeFilter.ANY_DIFF));

      return treeWalk.next();
    }
  }
예제 #18
0
  /*
   * Use the binary git repo and/or the remote service to figure out
   * the new commits made since the last pull on source repository.
   */
  public void findNewCommits() throws GitException {

    // get the history from binary repository
    Git bingit = Git.wrap(binaryRepository);
    RevWalk binwalk = new RevWalk(binaryRepository);

    Iterable<RevCommit> logs;
    try {
      logs = bingit.log().call();
      Iterator<RevCommit> i = logs.iterator();

      while (i.hasNext()) {
        RevCommit commit = binwalk.parseCommit(i.next());
        System.out.println(commit.getFullMessage());
      }

    } catch (NoHeadException e) {
      // TODO Auto-generated catch block
      throw new GitException(e);
    } catch (GitAPIException e) {
      throw new GitException(e);
    } catch (MissingObjectException e) {
      throw new GitException(e);
    } catch (IncorrectObjectTypeException e) {
      throw new GitException(e);
    } catch (IOException e) {
      throw new GitException(e);
    }
  }
예제 #19
0
파일: Log.java 프로젝트: roewenstrunk/eXgit
  @Override
  public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {

    try {
      String localPath = args[0].getStringValue();
      if (!(localPath.endsWith("/"))) localPath += File.separator;

      //	        Repository localRepo = new FileRepository(localPath + ".git");
      //	        Git git = new Git(localRepo);

      Git git = Git.open(new Resource(localPath), FS);

      MemTreeBuilder builder = context.getDocumentBuilder();

      AttributesImpl attribs = new AttributesImpl();
      attribs.addAttribute(NAMESPACE_URI, "local-path", PREFIX + ":local-path", "CDATA", localPath);

      int nodeNr = builder.startElement(LOG_ELEMENT, attribs);

      for (RevCommit commit : git.log().call()) {
        //                commit.getParentCount();
        //                commit.getParents();

        attribs = new AttributesImpl();
        attribs.addAttribute(NAMESPACE_URI, "id", PREFIX + ":id", "CDATA", commit.name());

        attribs.addAttribute(
            NAMESPACE_URI,
            "time",
            PREFIX + ":time",
            "CDATA",
            String.valueOf(commit.getCommitTime()));

        builder.startElement(COMMIT_ELEMENT, attribs);

        PersonIdent authorIdent = commit.getAuthorIdent();
        builder.startElement(AUTHOR_ELEMENT, null);
        builder.startElement(AUTHOR_NAME_ELEMENT, null);
        builder.characters(authorIdent.getName());
        builder.endElement();
        builder.startElement(AUTHOR_EMAIL_ELEMENT, null);
        builder.characters(authorIdent.getEmailAddress());
        builder.endElement();
        builder.endElement();

        builder.startElement(MESSAGE_ELEMENT, null);
        builder.characters(commit.getFullMessage());
        builder.endElement();

        builder.endElement();
      }

      builder.endElement();

      return builder.getDocument().getNode(nodeNr);
    } catch (Throwable e) {
      throw new XPathException(this, Module.EXGIT001, e);
    }
  }
예제 #20
0
 private static BlameInfo toBlameInfo(RevCommit commit, PersonIdent sourceAuthor) {
   BlameInfo blameInfo = new BlameInfo();
   blameInfo.author = sourceAuthor.getName();
   blameInfo.id = commit.getName();
   blameInfo.commitMsg = commit.getFullMessage();
   blameInfo.time = commit.getCommitTime();
   return blameInfo;
 }
예제 #21
0
파일: GitUtils.java 프로젝트: snjeza/core
  public static List<String> getLogForCurrentBranch(final Git repo) throws GitAPIException {
    List<String> results = new ArrayList<String>();
    Iterable<RevCommit> commits = repo.log().call();

    for (RevCommit commit : commits) results.add(commit.getFullMessage());

    return results;
  }
예제 #22
0
 @Override
 public int compare(@NotNull RevCommit o1, @NotNull RevCommit o2) {
   if (o1.getCommitTime() != o2.getCommitTime()) {
     return o1.getCommitTime() - o2.getCommitTime();
   } else {
     return o1.compareTo(o2);
   }
 }
예제 #23
0
 private GitVersionInfo makeVersionInfo(RevCommit revCommit) {
   PersonIdent authorIdent = revCommit.getAuthorIdent();
   return new GitVersionInfo(
       revCommit.name(),
       authorIdent.getName(),
       authorIdent.getWhen(),
       revCommit.getShortMessage());
 }
 private static boolean isSameParents(RevCommit prior, RevCommit next) {
   if (prior.getParentCount() != next.getParentCount()) {
     return false;
   } else if (prior.getParentCount() == 0) {
     return true;
   }
   return prior.getParent(0).equals(next.getParent(0));
 }
  @Test
  public void testUsingHiddenDeltaBaseFails() throws Exception {
    byte[] delta = {0x1, 0x1, 0x1, 'c'};
    TestRepository<Repository> s = new TestRepository<Repository>(src);
    RevCommit N =
        s.commit()
            .parent(B)
            .add("q", s.blob(BinaryDelta.apply(dst.open(b).getCachedBytes(), delta)))
            .create();

    final TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024);
    packHeader(pack, 3);
    copy(pack, src.open(N));
    copy(pack, src.open(s.parseBody(N).getTree()));
    pack.write((Constants.OBJ_REF_DELTA) << 4 | 4);
    b.copyRawTo(pack);
    deflate(pack, delta);
    digest(pack);

    final TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024);
    final PacketLineOut inPckLine = new PacketLineOut(inBuf);
    inPckLine.writeString(
        ObjectId.zeroId().name()
            + ' '
            + N.name()
            + ' '
            + "refs/heads/s"
            + '\0'
            + BasePackPushConnection.CAPABILITY_REPORT_STATUS);
    inPckLine.end();
    pack.writeTo(inBuf, PM);

    final TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024);
    final ReceivePack rp = new ReceivePack(dst);
    rp.setCheckReceivedObjects(true);
    rp.setCheckReferencedObjectsAreReachable(true);
    rp.setAdvertiseRefsHook(new HidePrivateHook());
    try {
      receive(rp, inBuf, outBuf);
      fail("Expected UnpackException");
    } catch (UnpackException failed) {
      Throwable err = failed.getCause();
      assertTrue(err instanceof MissingObjectException);
      MissingObjectException moe = (MissingObjectException) err;
      assertEquals(b, moe.getObjectId());
    }

    final PacketLineIn r = asPacketLineIn(outBuf);
    String master = r.readString();
    int nul = master.indexOf('\0');
    assertTrue("has capability list", nul > 0);
    assertEquals(B.name() + ' ' + R_MASTER, master.substring(0, nul));
    assertSame(PacketLineIn.END, r.readString());

    assertEquals("unpack error Missing blob " + b.name(), r.readString());
    assertEquals("ng refs/heads/s n/a (unpacker error)", r.readString());
    assertSame(PacketLineIn.END, r.readString());
  }
예제 #26
0
 /**
  * Parse a commit from its canonical format.
  *
  * <p>This method inserts the commit directly into the caller supplied revision pool, making it
  * appear as though the commit exists in the repository, even if it doesn't. The repository under
  * the pool is not affected.
  *
  * @param rw the revision pool to allocate the commit within. The commit's tree and parent
  *     pointers will be obtained from this pool.
  * @param raw the canonical formatted commit to be parsed.
  * @return the parsed commit, in an isolated revision pool that is not available to the caller.
  * @throws IOException in case of RevWalk initialization fails
  */
 public static RevCommit parse(RevWalk rw, byte[] raw) throws IOException {
   ObjectInserter.Formatter fmt = new ObjectInserter.Formatter();
   boolean retain = rw.isRetainBody();
   rw.setRetainBody(true);
   RevCommit r = rw.lookupCommit(fmt.idFor(Constants.OBJ_COMMIT, raw));
   r.parseCanonical(rw, raw);
   rw.setRetainBody(retain);
   return r;
 }
예제 #27
0
 private Revision asRevision(final RevCommit commit) {
   final PersonIdent author = commit.getAuthorIdent();
   return new RevisionImpl(
       commit.name(),
       author.getName(),
       author.getEmailAddress(),
       author.getWhen(),
       commit.getFullMessage());
 }
예제 #28
0
  private void setSourceCommit(RevCommit commit) {
    sourceNameLabel.setText(commit.abbreviate(7).name());
    sourceIcon.setImage(UIIcons.getImage(resourceManager, UIIcons.CHANGESET));

    sourceRefName = commit.name();

    upstreamConfig = UpstreamConfig.NONE;
    checkPage();
  }
  public Object execute(ExecutionEvent event) throws ExecutionException {
    List<StashedCommitNode> nodes = getSelectedNodes(event);
    if (nodes.isEmpty()) return null;

    StashedCommitNode node = nodes.get(0);
    final Repository repo = node.getRepository();
    if (repo == null) return null;
    final int index = node.getIndex();
    if (index < 0) return null;
    final RevCommit commit = node.getObject();
    if (commit == null) return null;

    // Confirm deletion of selected tags
    final AtomicBoolean confirmed = new AtomicBoolean();
    final Shell shell = getActiveShell(event);
    shell
        .getDisplay()
        .syncExec(
            new Runnable() {

              public void run() {
                confirmed.set(
                    MessageDialog.openConfirm(
                        shell,
                        UIText.StashDropCommand_confirmTitle,
                        MessageFormat.format(
                            UIText.StashDropCommand_confirmMessage, Integer.toString(index))));
              }
            });
    if (!confirmed.get()) return null;

    final StashDropOperation op = new StashDropOperation(repo, index);
    Job job =
        new Job(MessageFormat.format(UIText.StashDropCommand_jobTitle, commit.name())) {
          @Override
          protected IStatus run(IProgressMonitor monitor) {
            try {
              op.execute(monitor);
            } catch (CoreException e) {
              Activator.logError(
                  MessageFormat.format(UIText.StashDropCommand_dropFailed, commit.name()), e);
            }
            return Status.OK_STATUS;
          }

          @Override
          public boolean belongsTo(Object family) {
            if (JobFamilies.STASH.equals(family)) return true;
            return super.belongsTo(family);
          }
        };
    job.setUser(true);
    job.setRule(op.getSchedulingRule());
    job.schedule();
    return null;
  }
 public PatchSetInfo get(RevWalk rw, RevCommit src, PatchSet.Id psi) throws IOException {
   rw.parseBody(src);
   PatchSetInfo info = new PatchSetInfo(psi);
   info.setSubject(src.getShortMessage());
   info.setMessage(src.getFullMessage());
   info.setAuthor(toUserIdentity(src.getAuthorIdent()));
   info.setCommitter(toUserIdentity(src.getCommitterIdent()));
   info.setRevId(src.getName());
   return info;
 }