예제 #1
0
 // the RevWalk must be reset by the caller upon return!
 private ArrayList<RevCommit> findCommits(
     RevWalk walk,
     ArrayList<RevCommit> included,
     ArrayList<RevCommit> excluded,
     boolean getBody,
     long after)
     throws MissingObjectException, IncorrectObjectTypeException, IOException {
   ArrayList<RevCommit> commits = new ArrayList<RevCommit>();
   commits.ensureCapacity(allBranches.size()); // heuristic workaround
   walk.sort(RevSort.COMMIT_TIME_DESC, true);
   walk.sort(RevSort.TOPO, true);
   walk.setRetainBody(getBody);
   if (after > 0) walk.setRevFilter(CommitTimeRevFilter.after(after));
   else walk.setRevFilter(null);
   walk.markStart(included);
   RevCommit c;
   Iterator<RevCommit> it = excluded.iterator();
   while (it.hasNext()) {
     walk.markUninteresting(it.next());
   }
   it = walk.iterator();
   while (it.hasNext()) {
     c = it.next();
     if (getBody) walk.parseBody(c);
     // addUnique(commits, c); // commits are naturally ordered by SHA-1
     commits.add(c);
   }
   return commits.size() > 0 ? commits : null;
 }
예제 #2
0
  private void initRevPool(boolean reverse) {
    if (queue != null) throw new IllegalStateException();

    if (revPool != null) revPool.release();

    if (reverse) revPool = new ReverseWalk(getRepository());
    else revPool = new RevWalk(getRepository());

    revPool.setRetainBody(true);
    SEEN = revPool.newFlag("SEEN"); // $NON-NLS-1$
    reader = revPool.getObjectReader();
    treeWalk = new TreeWalk(reader);
    treeWalk.setRecursive(true);
  }
  protected static RevCommit resolveCommitIdByTagName(Repository repository, String tagName)
      throws IOException, GitAPIException {
    if (tagName == null || tagName.isEmpty()) return null;
    RevCommit revCommit = null;
    Map<String, Ref> tagMap = repository.getTags();
    Ref ref = tagMap.get(tagName);
    if (ref != null) {
      RevWalk walk = new RevWalk(repository);
      // some reduce memory effors as described in jgit user guide
      walk.setRetainBody(false);
      ObjectId from;

      from = repository.resolve("refs/heads/master");
      if (from == null) {
        Git git = new Git(repository);
        String lastTagName = git.describe().call();
        from = repository.resolve("refs/tags/" + lastTagName);
      }
      ObjectId to = repository.resolve("refs/remotes/origin/master");

      if (from == null) {
        throw new IllegalStateException("cannot determinate start commit");
      }
      walk.markStart(walk.parseCommit(from));
      walk.markUninteresting(walk.parseCommit(to));
      try {

        RevObject revObject = walk.parseAny(ref.getObjectId());
        if (revObject != null) {
          revCommit = walk.parseCommit(revObject.getId());
        }

      } finally {
        walk.close();
      }
    }

    return revCommit;
  }
예제 #4
0
  @Override
  public void execute() throws BuildException {
    if (_property == null) {
      throw new BuildException("Property attribute is required", getLocation());
    }

    if (_path == null) {
      throw new BuildException("Path attribute is required", getLocation());
    }

    File gitDir = PathUtil.getGitDir(_gitDir, getProject(), getLocation());

    String relativePath = PathUtil.toRelativePath(gitDir, _path);

    if (_useCache) {
      String hash = _hashes.get(relativePath);

      if (hash != null) {
        Project currentProject = getProject();

        currentProject.setNewProperty(_property, hash);

        return;
      }
    }

    try (Repository repository = RepositoryCache.open(FileKey.exact(gitDir, FS.DETECTED))) {

      RevWalk revWalk = new RevWalk(repository);

      revWalk.setRetainBody(false);

      revWalk.markStart(revWalk.parseCommit(repository.resolve(Constants.HEAD)));

      if (_ignoreFileName == null) {
        revWalk.setRevFilter(MaxCountRevFilter.create(1));
      } else {
        revWalk.setRevFilter(MaxCountRevFilter.create(2));
      }

      revWalk.setTreeFilter(
          AndTreeFilter.create(PathFilter.create(relativePath), TreeFilter.ANY_DIFF));

      RevCommit revCommit = revWalk.next();

      if (revCommit == null) {
        throw new IllegalStateException("Unable to find any commit under " + _path);
      }

      if (hasIgnoreFile(repository, revCommit, relativePath)) {
        RevCommit secondRevCommit = revWalk.next();

        if (secondRevCommit != null) {
          revCommit = secondRevCommit;
        }
      }

      Project currentProject = getProject();

      String hash = revCommit.name();

      currentProject.setNewProperty(_property, hash);

      if (_useCache) {
        _hashes.put(relativePath, hash);
      }

      revWalk.dispose();
    } catch (Exception e) {
      throw new BuildException("Unable to get head hash for path " + _path, e);
    }
  }
예제 #5
0
  public String getProjectVersion(File repoDir) throws IOException, GitAPIException {
    Git git = Git.open(repoDir);
    Repository repo = git.getRepository();

    // Find base commit between current branch and "master":
    String branch = repo.getBranch();
    RevCommit base = CommitUtils.getBase(repo, "master", branch);
    CommitCountFilter count = new CommitCountFilter();
    CommitFinder finder = new CommitFinder(repo).setFilter(count);
    finder.findBetween(branch, base);
    long commitsSinceBase = count.getCount();

    // Find tags in "master" before base commit:
    RevWalk rw = new RevWalk(repo);
    rw.markStart(base);
    rw.setRetainBody(false);
    Ref master = repo.getRef("master");
    List<Ref> masterAsList = Arrays.asList(master);
    List<Ref> tags = git.tagList().call();
    Map<RevCommit, Ref> masterTags = new HashMap<RevCommit, Ref>();
    for (Ref tag : tags) {
      tag = repo.peel(tag);
      ObjectId commitID = tag.getPeeledObjectId();
      if (commitID == null) continue;
      RevCommit commit = rw.parseCommit(commitID);
      // Only remember tags reachable from "master":
      if (!RevWalkUtils.findBranchesReachableFrom(commit, rw, masterAsList).isEmpty()) {
        masterTags.put(commit, tag);
      }
    }

    // Find the shortest distance in commits between base tag in "master":
    long commitsBetweenBaseAndTag = Long.MAX_VALUE;
    String tagName = "";
    for (RevCommit tagCommit : masterTags.keySet()) {
      count.reset();
      finder.findBetween(base, tagCommit);
      if (count.getCount() < commitsBetweenBaseAndTag) {
        commitsBetweenBaseAndTag = count.getCount();
        tagName = masterTags.get(tagCommit).getName();
      }
    }
    if (commitsBetweenBaseAndTag == Long.MAX_VALUE) {
      // If no tag, get total number of commits:
      commitsBetweenBaseAndTag = repo.getRefDatabase().getRefs("").size();
    }
    long commitsSinceLastMasterTag = commitsSinceBase + commitsBetweenBaseAndTag;

    // Construct version string:
    String version = branch.equals("master") ? "" : (branch + "-");
    if (tagName.startsWith("refs/tags/")) {
      tagName = tagName.substring("refs/tags/".length());
    }
    // v1.1 -> 1.1
    if (tagName.matches("v\\d+.*")) {
      tagName = tagName.substring(1);
    }
    if (tagName.isEmpty()) {
      version = "0";
    }
    version += tagName + ((!tagonly) ? "." + commitsSinceLastMasterTag : "");

    return version;
  }
예제 #6
0
  @Override
  public Document execute(
      Repository repository, Git git, CallSpecification spec, DocumentWriter writer, Values values)
      throws GitAPIException, IOException {
    if (spec.parameterCount() == 0) {
      // This is the top-level "/branches" node
      writer.setPrimaryType(GitLexicon.TREES);

      // Generate the child references to the branches and tags. Branches are likely used more
      // often, so list them first...
      addBranchesAsChildren(git, spec, writer);
      addTagsAsChildren(git, spec, writer);
      addCommitsAsChildren(git, spec, writer, pageSize);

    } else if (spec.parameterCount() == 1) {
      // This is a particular branch/tag/commit node ...
      String branchOrTagOrObjectId = spec.parameter(0);
      ObjectId objId = resolveBranchOrTagOrCommitId(repository, branchOrTagOrObjectId);
      RevWalk walker = new RevWalk(repository);
      walker.setRetainBody(true); // we need to parse the commit for the top-level
      try {
        RevCommit commit = walker.parseCommit(objId);

        // Add the properties for this node ...
        String committer = commit.getCommitterIdent().getName();
        String author = commit.getAuthorIdent().getName();
        DateTime committed = values.dateFrom(commit.getCommitTime());
        writer.setPrimaryType(GitLexicon.FOLDER);
        writer.addProperty(JcrLexicon.CREATED, committed);
        writer.addProperty(JcrLexicon.CREATED_BY, committer);
        writer.addProperty(GitLexicon.OBJECT_ID, objId.name());
        writer.addProperty(GitLexicon.AUTHOR, author);
        writer.addProperty(GitLexicon.COMMITTER, committer);
        writer.addProperty(GitLexicon.COMMITTED, committed);
        writer.addProperty(GitLexicon.TITLE, commit.getShortMessage());
        writer.addProperty(
            GitLexicon.HISTORY,
            GitHistory.referenceToHistory(objId, branchOrTagOrObjectId, values));
        writer.addProperty(GitLexicon.DETAIL, GitCommitDetails.referenceToCommit(objId, values));

        // Add the top-level children of the directory ...
        addInformationForPath(repository, git, writer, commit, "", spec, values);

      } finally {
        walker.dispose();
      }

    } else {
      // This is a folder or file within the directory structure ...
      String branchOrTagOrObjectId = spec.parameter(0);
      String path = spec.parametersAsPath(1);
      ObjectId objId = resolveBranchOrTagOrCommitId(repository, branchOrTagOrObjectId);
      RevWalk walker = new RevWalk(repository);
      walker.setRetainBody(false); // we don't need top-level commit information
      try {
        // Get the commit information ...
        RevCommit commit = walker.parseCommit(objId);

        // Add the top-level children of the directory ...
        addInformationForPath(repository, git, writer, commit, path, spec, values);

      } finally {
        walker.dispose();
      }
    }
    return writer.document();
  }
예제 #7
0
  @NonNull
  @Override
  protected void retrieve(@NonNull final SCMHeadObserver observer, @NonNull TaskListener listener)
      throws IOException, InterruptedException {
    String cacheEntry = getCacheEntry();
    Lock cacheLock = getCacheLock(cacheEntry);
    cacheLock.lock();
    try {
      File cacheDir = getCacheDir(cacheEntry);
      Git git =
          Git.with(listener, new EnvVars(System.getenv()))
              .in(cacheDir)
              .using(GitTool.getDefaultInstallation().getGitExe());
      GitClient client = git.getClient();
      client.addDefaultCredentials(getCredentials());
      if (!client.hasGitRepo()) {
        listener.getLogger().println("Creating git repository in " + cacheDir);
        client.init();
      }
      String remoteName = getRemoteName();
      listener.getLogger().println("Setting " + remoteName + " to " + getRemote());
      client.setRemoteUrl(remoteName, getRemote());
      listener.getLogger().println("Fetching " + remoteName + "...");
      List<RefSpec> refSpecs = getRefSpecs();
      client.fetch(remoteName, refSpecs.toArray(new RefSpec[refSpecs.size()]));
      listener.getLogger().println("Pruning stale remotes...");
      final Repository repository = client.getRepository();
      try {
        client.prune(new RemoteConfig(repository.getConfig(), remoteName));
      } catch (UnsupportedOperationException e) {
        e.printStackTrace(listener.error("Could not prune stale remotes"));
      } catch (URISyntaxException e) {
        e.printStackTrace(listener.error("Could not prune stale remotes"));
      }
      listener.getLogger().println("Getting remote branches...");
      SCMSourceCriteria branchCriteria = getCriteria();
      RevWalk walk = new RevWalk(repository);
      try {
        walk.setRetainBody(false);
        for (Branch b : client.getRemoteBranches()) {
          if (!b.getName().startsWith(remoteName + "/")) {
            continue;
          }
          final String branchName = StringUtils.removeStart(b.getName(), remoteName + "/");
          listener.getLogger().println("Checking branch " + branchName);
          if (isExcluded(branchName)) {
            continue;
          }
          if (branchCriteria != null) {
            RevCommit commit = walk.parseCommit(b.getSHA1());
            final long lastModified = TimeUnit.SECONDS.toMillis(commit.getCommitTime());
            final RevTree tree = commit.getTree();
            SCMSourceCriteria.Probe probe =
                new SCMSourceCriteria.Probe() {
                  @Override
                  public String name() {
                    return branchName;
                  }

                  @Override
                  public long lastModified() {
                    return lastModified;
                  }

                  @Override
                  public boolean exists(@NonNull String path) throws IOException {
                    TreeWalk tw = TreeWalk.forPath(repository, path, tree);
                    try {
                      return tw != null;
                    } finally {
                      if (tw != null) {
                        tw.release();
                      }
                    }
                  }
                };
            if (branchCriteria.isHead(probe, listener)) {
              listener.getLogger().println("Met criteria");
            } else {
              listener.getLogger().println("Does not meet criteria");
              continue;
            }
          }
          SCMHead head = new SCMHead(branchName);
          SCMRevision hash = new SCMRevisionImpl(head, b.getSHA1String());
          observer.observe(head, hash);
          if (!observer.isObserving()) {
            return;
          }
        }
      } finally {
        walk.dispose();
      }

      listener.getLogger().println("Done.");
    } finally {
      cacheLock.unlock();
    }
  }