Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jgit-dev] GitBlit Pre/Post Receive Hook

On Wed, Mar 19, 2014 at 10:32 AM, Michael Quigley <michael@xxxxxxxxxxx> wrote:
> I've been struggling trying to figure out the correct way to implement a
> pre/post-receive hook for GitBlit (which embeds JGit). In my hook, I need to
> reliably determine which commits are being pushed to the server, despite
> whichever refs are involved. I've tried a couple of things with various
> levels of success.
>
> I've also been struggling to find support for this. I'm here now, and I
> apologize if this is off-topic for this list. But I'm floundering with this,
> and I'd really appreciate any help you can offer.
>
> I'm using code like this in my hook:
>
> for(ReceiveCommand command : c.commands) {
>         log.info("refname = " + command.getRefName());
>
>         String oldId = ObjectId.zeroId().getName();
>         ObjectId old = r.resolve(command.getRefName());
>         if(old != null) {
>                 oldId = old.getName();
>         }
>         String newId = command.getNewId().getName();
>         log.info("Inspecting commits in range [" + oldId + "] -> [" + newId
> + "].");
>
>         List<RevCommit> commits = GitUtility.getRevLog(r, oldId, newId);
>         Collections.reverse(commits);
>
>         log.info("Found " + commits.size() + " commits.");
> }
>
> And GitUtility.getRevlog() looks like this:
>
> public static List<RevCommit> getRevLog(Repository repository, String
> startRangeId, String endRangeId) {

Passing string is weird when you have ObjectId above, but OK.

>         List<RevCommit> list = new ArrayList<RevCommit>();
>         if(!hasCommits(repository)) {
>                 return list;
>         }
>
>         try {
>                 ObjectId endRange = repository.resolve(endRangeId);
>                 ObjectId startRange = repository.resolve(startRangeId);
>
>                 RevWalk rw = new RevWalk(repository);
>                 rw.markStart(rw.parseCommit(endRange));
>                 if(!startRange.equals(ObjectId.zeroId())) {
>                        rw.markUninteresting(rw.parseCommit(startRange));
>                 }

This is your problem.

When the branch or tag is being created startRange is
ObjectId.zeroId(). This causes you to omit the markUninteresting()
case and list the entire history.

I think you want to do so something like this:

  if (startRange.equals(ObjectId.zeroId()) {
    for (Ref ref : repository.getAllRefs()) {
      if (ref.getObjectId() != null) {
        try {
          rw.markUninteresting(rw.parseCommit(ref.getObjectId()));
         } catch (IncorrectObjectTypeException e) {
           // Ignore non-commits.
         }
      }
    }
  } else {
    rw.markUninteresting(startRange);
  }

So for new branches and tags the code will skip commits already
reachable from existing branches and tags, listing only entirely new
commits.

> This works fine most of the time. But for some pushes on branches and tags,
> this code ends up traversing the entire commit history, which is a huge
> problem for the integration I'm trying to develop.

See above.


Back to the top