예제 #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 negotiateBegin() throws IOException {
    walk.resetRetain(REACHABLE, ADVERTISED);
    walk.markStart(reachableCommits);
    walk.sort(RevSort.COMMIT_TIME_DESC);
    walk.setRevFilter(
        new RevFilter() {
          @Override
          public RevFilter clone() {
            return this;
          }

          @Override
          public boolean include(final RevWalk walker, final RevCommit c) {
            final boolean remoteKnowsIsCommon = c.has(COMMON);
            if (c.has(ADVERTISED)) {
              // Remote advertised this, and we have it, hence common.
              // Whether or not the remote knows that fact is tested
              // before we added the flag. If the remote doesn't know
              // we have to still send them this object.
              //
              c.add(COMMON);
            }
            return !remoteKnowsIsCommon;
          }
        });
  }
예제 #3
0
  /**
   * Parses an array of Git commits and returns an array of commits that affected the specified
   * object.
   *
   * @param repository the Git repository
   * @param commitIds the Git commit IDs to parse
   * @param path the object affected
   * @return an array of {@link GitCommit} objects representing the commits
   */
  public NSArray<GitCommit> commitsWithIds(NSArray<ObjectId> commitIds, String path) {
    try {
      RevWalk rw = new RevWalk(repository);

      try {
        rw.sort(RevSort.COMMIT_TIME_DESC);

        if (path != null) {
          rw.setTreeFilter(
              AndTreeFilter.create(PathSuffixFilter.create(path), TreeFilter.ANY_DIFF));
        } else {
          rw.setTreeFilter(TreeFilter.ALL);
        }

        for (ObjectId commitId : commitIds) {
          rw.markStart(rw.parseCommit(commitId));
        }

        NSMutableArray<GitCommit> commits = new NSMutableArray<GitCommit>();

        for (RevCommit commit : rw) {
          commits.add(new GitCommit(commit));
        }

        return commits;
      } finally {
        rw.release();
      }
    } catch (Exception e) {
      log.error("An exception occurred while parsing the commit: ", e);
      return null;
    }
  }
예제 #4
0
  /**
   * Returns a list of commits since the minimum date starting from the specified object id.
   *
   * @param repository
   * @param objectId if unspecified, HEAD is assumed.
   * @param minimumDate
   * @return list of commits
   */
  public static List<RevCommit> getRevLog(
      Repository repository, String objectId, Date minimumDate) {
    List<RevCommit> list = new ArrayList<RevCommit>();
    if (!hasCommits(repository)) {
      return list;
    }
    try {
      // resolve branch
      ObjectId branchObject;
      if (objectId == null) {
        branchObject = getDefaultBranch(repository);
      } else {
        branchObject = repository.resolve(objectId);
      }

      RevWalk rw = new RevWalk(repository);
      rw.markStart(rw.parseCommit(branchObject));
      rw.setRevFilter(CommitTimeRevFilter.after(minimumDate));
      Iterable<RevCommit> revlog = rw;
      for (RevCommit rev : revlog) {
        list.add(rev);
      }
      rw.dispose();
    } catch (Throwable t) {
      // todo
      Logger.error(t, t.getMessage());
    }
    return list;
  }
예제 #5
0
  public void markCleanMerges(
      final RevWalk rw,
      final RevFlag canMergeFlag,
      final CodeReviewCommit mergeTip,
      final Set<RevCommit> alreadyAccepted)
      throws IntegrationException {
    if (mergeTip == null) {
      // If mergeTip is null here, branchTip was null, indicating a new branch
      // at the start of the merge process. We also elected to merge nothing,
      // probably due to missing dependencies. Nothing was cleanly merged.
      //
      return;
    }

    try {
      rw.resetRetain(canMergeFlag);
      rw.sort(RevSort.TOPO);
      rw.sort(RevSort.REVERSE, true);
      rw.markStart(mergeTip);
      for (RevCommit c : alreadyAccepted) {
        rw.markUninteresting(c);
      }

      CodeReviewCommit c;
      while ((c = (CodeReviewCommit) rw.next()) != null) {
        if (c.getPatchsetId() != null) {
          c.setStatusCode(CommitMergeStatus.CLEAN_MERGE);
        }
      }
    } catch (IOException e) {
      throw new IntegrationException("Cannot mark clean merges", e);
    }
  }
예제 #6
0
 protected List<RevCommit> getRemoteLog(Project.NameKey project, String branch)
     throws IOException {
   try (Repository repo = repoManager.openRepository(project);
       RevWalk rw = new RevWalk(repo)) {
     rw.markStart(rw.parseCommit(repo.getRef("refs/heads/" + branch).getObjectId()));
     return Lists.newArrayList(rw);
   }
 }
예제 #7
0
  /**
   * Returns a list of commits for the repository or a path within the repository. Caller may
   * specify ending revision with objectId. Caller may specify offset and maxCount to achieve
   * pagination of results. If the repository does not exist or is empty, an empty list is returned.
   *
   * @param repository
   * @param objectId if unspecified, HEAD is assumed.
   * @param path if unspecified, commits for repository are returned. If specified, commits for the
   *     path are returned.
   * @param offset
   * @param maxCount if < 0, all commits are returned.
   * @return a paged list of commits
   */
  public static List<RevCommit> getRevLog(
      Repository repository, String objectId, String path, int offset, int maxCount) {
    List<RevCommit> list = new ArrayList<RevCommit>();
    if (maxCount == 0) {
      return list;
    }
    if (!hasCommits(repository)) {
      return list;
    }
    try {
      // resolve branch
      ObjectId branchObject;
      if (objectId == null) {
        branchObject = getDefaultBranch(repository);
      } else {
        branchObject = repository.resolve(objectId);
      }

      RevWalk rw = new RevWalk(repository);
      rw.markStart(rw.parseCommit(branchObject));
      if (!(path == null)) {
        TreeFilter filter =
            AndTreeFilter.create(
                PathFilterGroup.createFromStrings(Collections.singleton(path)),
                TreeFilter.ALL); // TreeFilter.ANY_DIFF
        rw.setTreeFilter(filter);
      }
      Iterable<RevCommit> revlog = rw;
      if (offset > 0) {
        int count = 0;
        for (RevCommit rev : revlog) {
          count++;
          if (count > offset) {
            list.add(rev);
            if (maxCount > 0 && list.size() == maxCount) {
              break;
            }
          }
        }
      } else {
        for (RevCommit rev : revlog) {
          list.add(rev);
          if (maxCount > 0 && list.size() == maxCount) {
            break;
          }
        }
      }
      rw.dispose();
    } catch (Throwable t) {
      // todo
      Logger.error(t, t.getMessage());
    }
    return list;
  }
예제 #8
0
 private static boolean isReachable(Repository repo, AnyObjectId id) throws IOException {
   try (RevWalk rw = new RevWalk(repo)) {
     for (Ref ref : repo.getAllRefs().values()) {
       rw.markStart(rw.parseCommit(ref.getObjectId()));
     }
     for (RevCommit next; (next = rw.next()) != null; ) {
       if (AnyObjectId.equals(next, id)) {
         return true;
       }
     }
   }
   return false;
 }
예제 #9
0
  private void markReachable(final Set<ObjectId> have, final int maxTime) throws IOException {
    for (final Ref r : local.getAllRefs().values()) {
      try {
        final RevCommit o = walk.parseCommit(r.getObjectId());
        o.add(REACHABLE);
        reachableCommits.add(o);
      } catch (IOException readError) {
        // If we cannot read the value of the ref skip it.
      }
    }

    for (final ObjectId id : have) {
      try {
        final RevCommit o = walk.parseCommit(id);
        o.add(REACHABLE);
        reachableCommits.add(o);
      } catch (IOException readError) {
        // If we cannot read the value of the ref skip it.
      }
    }

    if (maxTime > 0) {
      // Mark reachable commits until we reach maxTime. These may
      // wind up later matching up against things we want and we
      // can avoid asking for something we already happen to have.
      //
      final Date maxWhen = new Date(maxTime * 1000L);
      walk.sort(RevSort.COMMIT_TIME_DESC);
      walk.markStart(reachableCommits);
      walk.setRevFilter(CommitTimeRevFilter.after(maxWhen));
      for (; ; ) {
        final RevCommit c = walk.next();
        if (c == null) break;
        if (c.has(ADVERTISED) && !c.has(COMMON)) {
          // This is actually going to be a common commit, but
          // our peer doesn't know that fact yet.
          //
          c.add(COMMON);
          c.carry(COMMON);
          reachableCommits.add(c);
        }
      }
    }
  }
예제 #10
0
  /**
   * Configure the generator to compute reverse blame (history of deletes).
   *
   * <p>This method is expensive as it immediately runs a RevWalk over the history spanning the
   * expression {@code start..end} (end being more recent than start) and then performs the
   * equivalent operation as {@link #push(String, AnyObjectId)} to begin blame traversal from the
   * commit named by {@code start} walking forwards through history until {@code end} blaming line
   * deletions.
   *
   * <p>A reverse blame may produce multiple sources for the same result line, each of these is a
   * descendant commit that removed the line, typically this occurs when the same deletion appears
   * in multiple side branches such as due to a cherry-pick. Applications relying on reverse should
   * use {@link BlameResult} as it filters these duplicate sources and only remembers the first
   * (oldest) deletion.
   *
   * @param start oldest commit to traverse from. The result file will be loaded from this commit's
   *     tree.
   * @param end most recent commits to stop traversal at. Usually an active branch tip, tag, or
   *     HEAD.
   * @return {@code this}
   * @throws IOException the repository cannot be read.
   */
  public BlameGenerator reverse(AnyObjectId start, Collection<? extends ObjectId> end)
      throws IOException {
    initRevPool(true);

    ReverseCommit result = (ReverseCommit) revPool.parseCommit(start);
    if (!find(result, resultPath)) return this;

    revPool.markUninteresting(result);
    for (ObjectId id : end) revPool.markStart(revPool.parseCommit(id));

    while (revPool.next() != null) {
      // just pump the queue
    }

    ReverseCandidate c = new ReverseCandidate(result, resultPath);
    c.sourceBlob = idBuf.toObjectId();
    c.loadText(reader);
    c.regionList = new Region(0, 0, c.sourceText.size());
    remaining = c.sourceText.size();
    push(c);
    return this;
  }
  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;
  }
예제 #12
0
  @NotNull
  public SortedSet<RevCommit> calculate(@NotNull String branchName, @Nullable RevFilter revFilter)
      throws IOException {
    Ref head = myRepository.getRef(branchName);

    if (head == null) {
      throw new IllegalArgumentException("Branch does not exist: [branchName: " + branchName + "]");
    }

    myRevWalk.markStart(myRevWalk.parseCommit(head.getObjectId()));
    myRevWalk.setRevFilter(revFilter);

    SortedSet<RevCommit> roots = new TreeSet<>(REV_COMMIT_COMPARATOR);

    for (RevCommit commit : myRevWalk) {
      roots.add(commit);
    }

    myRevWalk.reset();
    myRevWalk.dispose();

    return roots;
  }
예제 #13
0
파일: Merger.java 프로젝트: abayer/jgit
  /**
   * Create an iterator to walk the merge base of two commits.
   *
   * @param aIdx index of the first commit in {@link #sourceObjects}.
   * @param bIdx index of the second commit in {@link #sourceObjects}.
   * @return the new iterator
   * @throws IncorrectObjectTypeException one of the input objects is not a commit.
   * @throws IOException objects are missing or multiple merge bases were found.
   */
  protected AbstractTreeIterator mergeBase(final int aIdx, final int bIdx) throws IOException {
    if (sourceCommits[aIdx] == null)
      throw new IncorrectObjectTypeException(sourceObjects[aIdx], Constants.TYPE_COMMIT);
    if (sourceCommits[bIdx] == null)
      throw new IncorrectObjectTypeException(sourceObjects[bIdx], Constants.TYPE_COMMIT);

    walk.reset();
    walk.setRevFilter(RevFilter.MERGE_BASE);
    walk.markStart(sourceCommits[aIdx]);
    walk.markStart(sourceCommits[bIdx]);
    final RevCommit base = walk.next();
    if (base == null) return new EmptyTreeIterator();
    final RevCommit base2 = walk.next();
    if (base2 != null) {
      throw new IOException(
          MessageFormat.format(
              JGitText.get().multipleMergeBasesFor,
              sourceCommits[aIdx].name(),
              sourceCommits[bIdx].name(),
              base.name(),
              base2.name()));
    }
    return openTree(base.getTree());
  }
예제 #14
0
  // printout all commit messages in a given range -> expensive: creates a one-time only RevWalk
  void printCommits(String outFile, String from_ref, String to_ref)
      throws IOException, NoHeadException, GitAPIException {

    AnyObjectId from = git.getRepository().resolve(from_ref);
    AnyObjectId to =
        (to_ref == null || to_ref.equals("")) ? null : git.getRepository().resolve(to_ref);
    RevWalk walk = new RevWalk(git.getRepository());
    walk.sort(RevSort.COMMIT_TIME_DESC, true);
    walk.sort(RevSort.TOPO, true);
    walk.markStart(walk.parseCommit(from));
    if (to != null) walk.markUninteresting(walk.parseCommit(to));

    printCommits(outFile, walk);
    walk.dispose();
    //  PrintWriter pout = new PrintWriter(new FileWriter(outFile), true);
    //  Iterator<RevCommit> itc = git.log().add(from).call().iterator();
    //  RevCommit c;
    //  while (itc.hasNext()) {
    //    c = itc.next();
    //    pout.println("===========\n" + printCommit(c));
    //    if (to != null && c.equals(to)) break;
    //  }
    //  pout.close();
  }
예제 #15
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;
  }
예제 #16
0
  /**
   * Update the submodules in one branch of one repository.
   *
   * @param subscriber the branch of the repository which should be changed.
   * @param updates submodule updates which should be updated to.
   * @throws SubmoduleException
   */
  private void updateGitlinks(
      ReviewDb db, Branch.NameKey subscriber, Collection<SubmoduleSubscription> updates)
      throws SubmoduleException {
    PersonIdent author = null;

    Repository pdb = null;
    RevWalk recRw = null;

    StringBuilder msgbuf = new StringBuilder("Updated git submodules\n\n");
    try {
      boolean sameAuthorForAll = true;

      pdb = repoManager.openRepository(subscriber.getParentKey());
      if (pdb.getRef(subscriber.get()) == null) {
        throw new SubmoduleException(
            "The branch was probably deleted from the subscriber repository");
      }

      DirCache dc = readTree(pdb, pdb.getRef(subscriber.get()));
      DirCacheEditor ed = dc.editor();

      for (SubmoduleSubscription s : updates) {
        try (Repository subrepo = repoManager.openRepository(s.getSubmodule().getParentKey());
            RevWalk rw = CodeReviewCommit.newRevWalk(subrepo)) {
          Ref ref = subrepo.getRefDatabase().exactRef(s.getSubmodule().get());
          if (ref == null) {
            ed.add(new DeletePath(s.getPath()));
            continue;
          }

          final ObjectId updateTo = ref.getObjectId();
          RevCommit newCommit = rw.parseCommit(updateTo);

          if (author == null) {
            author = newCommit.getAuthorIdent();
          } else if (!author.equals(newCommit.getAuthorIdent())) {
            sameAuthorForAll = false;
          }

          DirCacheEntry dce = dc.getEntry(s.getPath());
          ObjectId oldId = null;
          if (dce != null) {
            if (!dce.getFileMode().equals(FileMode.GITLINK)) {
              log.error(
                  "Requested to update gitlink "
                      + s.getPath()
                      + " in "
                      + s.getSubmodule().getParentKey().get()
                      + " but entry "
                      + "doesn't have gitlink file mode.");
              continue;
            }
            oldId = dce.getObjectId();
          } else {
            // This submodule did not exist before. We do not want to add
            // the full submodule history to the commit message, so omit it.
            oldId = updateTo;
          }

          ed.add(
              new PathEdit(s.getPath()) {
                @Override
                public void apply(DirCacheEntry ent) {
                  ent.setFileMode(FileMode.GITLINK);
                  ent.setObjectId(updateTo);
                }
              });
          if (verboseSuperProject) {
            msgbuf.append("Project: " + s.getSubmodule().getParentKey().get());
            msgbuf.append(" " + s.getSubmodule().getShortName());
            msgbuf.append(" " + updateTo.getName());
            msgbuf.append("\n\n");

            try {
              rw.markStart(newCommit);

              if (oldId != null) {
                rw.markUninteresting(rw.parseCommit(oldId));
              }
              for (RevCommit c : rw) {
                msgbuf.append(c.getFullMessage() + "\n\n");
              }
            } catch (IOException e) {
              logAndThrowSubmoduleException(
                  "Could not perform a revwalk to " + "create superproject commit message", e);
            }
          }
        }
      }
      ed.finish();

      if (!sameAuthorForAll || author == null) {
        author = myIdent;
      }

      ObjectInserter oi = pdb.newObjectInserter();
      ObjectId tree = dc.writeTree(oi);

      ObjectId currentCommitId = pdb.getRef(subscriber.get()).getObjectId();

      CommitBuilder commit = new CommitBuilder();
      commit.setTreeId(tree);
      commit.setParentIds(new ObjectId[] {currentCommitId});
      commit.setAuthor(author);
      commit.setCommitter(myIdent);
      commit.setMessage(msgbuf.toString());
      oi.insert(commit);
      oi.flush();

      ObjectId commitId = oi.idFor(Constants.OBJ_COMMIT, commit.build());

      final RefUpdate rfu = pdb.updateRef(subscriber.get());
      rfu.setForceUpdate(false);
      rfu.setNewObjectId(commitId);
      rfu.setExpectedOldObjectId(currentCommitId);
      rfu.setRefLogMessage("Submit to " + subscriber.getParentKey().get(), true);

      switch (rfu.update()) {
        case NEW:
        case FAST_FORWARD:
          gitRefUpdated.fire(subscriber.getParentKey(), rfu);
          changeHooks.doRefUpdatedHook(subscriber, rfu, account);
          // TODO since this is performed "in the background" no mail will be
          // sent to inform users about the updated branch
          break;

        default:
          throw new IOException(rfu.getResult().name());
      }
      recRw = new RevWalk(pdb);
      // Recursive call: update subscribers of the subscriber
      updateSuperProjects(db, Sets.newHashSet(subscriber));
    } catch (IOException e) {
      throw new SubmoduleException("Cannot update gitlinks for " + subscriber.get(), e);
    } finally {
      if (recRw != null) {
        recRw.close();
      }
      if (pdb != null) {
        pdb.close();
      }
    }
  }
예제 #17
0
  /**
   * Process the EGit history associated with a given project.
   *
   * @param selectedProject selected project, presumably an object contribution selection
   * @throws CoreException
   * @throws IOException
   */
  public void processHistory(IProject selectedProject, IProgressMonitor monitor)
      throws CoreException, IOException {

    // find the repository mapping for the project
    // if none found, return
    RepositoryMapping repositoryMapping = RepositoryMapping.getMapping((IResource) selectedProject);
    if (repositoryMapping == null) {
      CertWareLog.logWarning(
          String.format("%s %s", "Missing repository for project", selectedProject.getName()));
      return;
    }

    // build the commit history model, load it from the tree walk
    final CommitHistory commitHistory = ScoFactory.eINSTANCE.createCommitHistory();
    Repository repo = repositoryMapping.getRepository();
    RevWalk revWalk = new RevWalk(repo);
    ObjectId headObject = repo.resolve("HEAD");
    revWalk.markStart(revWalk.parseCommit(headObject));

    final Set<String> repositoryPaths =
        Collections.singleton(repositoryMapping.getRepoRelativePath(selectedProject));
    revWalk.setTreeFilter(PathFilterGroup.createFromStrings(repositoryPaths));

    for (RevCommit commit : revWalk) {
      String commitName = commit.getName();
      ArtifactCommit artifactCommit = ScoFactory.eINSTANCE.createArtifactCommit();
      artifactCommit.setCommitIdentifier(commitName);
      commitHistory.getCommitRecord().add(artifactCommit);
    }

    revWalk.dispose();

    // use the Git provider to find the file history, then converge into the model
    GitProvider provider = (GitProvider) RepositoryProvider.getProvider(selectedProject);
    IFileHistoryProvider fileHistoryProvider = provider.getFileHistoryProvider();
    IResource[] projectMembers = selectedProject.members();

    monitor.beginTask("Processing project resources", projectMembers.length);
    for (IResource resource : projectMembers) {
      processResource(resource, fileHistoryProvider, commitHistory, monitor);
      monitor.worked(1);
      if (monitor.isCanceled()) {
        return;
      }
    }

    // model complete with commit history and associated file sizes
    // write the resulting model to an SCO file
    // expecting preference to have no extension, so add it if necessary
    IPreferenceStore store = Activator.getDefault().getPreferenceStore();
    String fileName = store.getString(PreferenceConstants.P_FILENAME_SCO);
    if (fileName.endsWith(ICertWareConstants.SCO_EXTENSION) == false) {
      fileName = fileName + '.' + ICertWareConstants.SCO_EXTENSION;
    }

    // fully specify the path to the new file given the container project
    final String modelFile =
        selectedProject.getFullPath().toPortableString() + IPath.SEPARATOR + fileName;

    // create the resource in a workspace modify operation
    WorkspaceModifyOperation operation =
        new WorkspaceModifyOperation() {
          @Override
          protected void execute(IProgressMonitor progressMonitor) {
            try {
              // create a resource set and resource for a new file
              ResourceSet resourceSet = new ResourceSetImpl();
              URI fileURI = URI.createPlatformResourceURI(modelFile, true);
              Resource resource = resourceSet.createResource(fileURI);
              resource.getContents().add(commitHistory);

              // save the contents of the resource to the file system
              Map<Object, Object> options = new HashMap<Object, Object>();
              options.put(XMLResource.OPTION_ENCODING, FILE_ENCODING);
              resource.save(options);
            } catch (Exception e) {
              CertWareLog.logError(String.format("%s %s", "Saving SCO file", modelFile), e);
            }
          }
        };

    // modify the workspace
    try {
      operation.run(monitor);
    } catch (Exception e) {
      CertWareLog.logError(
          String.format("%s %s", "Modifying workspace for", selectedProject.getName()), e);
    }

    monitor.done();
  }
예제 #18
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);
    }
  }