Ejemplo n.º 1
0
  @Override
  public Revision decorateRevisionToBuild(
      GitSCM scm, AbstractBuild<?, ?> build, GitClient git, BuildListener listener, Revision rev)
      throws IOException, InterruptedException {
    String remoteBranchRef =
        GitSCM.getParameterString(options.getRef(), build.getEnvironment(listener));

    // if the branch we are merging is already at the commit being built, the entire merge becomes
    // no-op
    // so there's nothing to do
    if (rev.containsBranchName(remoteBranchRef)) return rev;

    // Only merge if there's a branch to merge that isn't us..
    listener
        .getLogger()
        .println(
            "Merging "
                + rev
                + " onto "
                + remoteBranchRef
                + " using "
                + scm.getUserMergeOptions().getMergeStrategy().toString()
                + " strategy");

    // checkout origin/blah
    ObjectId target = git.revParse(remoteBranchRef);

    String paramLocalBranch = scm.getParamLocalBranch(build);
    git.checkoutBranch(paramLocalBranch, remoteBranchRef);

    try {
      MergeCommand cmd = git.merge().setRevisionToMerge(rev.getSha1());
      for (GitSCMExtension ext : scm.getExtensions())
        ext.decorateMergeCommand(scm, build, git, listener, cmd);
      cmd.execute();
    } catch (GitException ex) {
      // merge conflict. First, avoid leaving any conflict markers in the working tree
      // by checking out some known clean state. We don't really mind what commit this is,
      // since the next build is going to pick its own commit to build, but 'rev' is as good any.
      git.checkoutBranch(paramLocalBranch, rev.getSha1String());

      // record the fact that we've tried building 'rev' and it failed, or else
      // BuildChooser in future builds will pick up this same 'rev' again and we'll see the exact
      // same merge failure
      // all over again.
      scm.getBuildData(build).saveBuild(new Build(rev, build.getNumber(), FAILURE));
      throw new AbortException("Branch not suitable for integration as it does not merge cleanly");
    }

    build.addAction(new MergeRecord(remoteBranchRef, target.getName()));

    return new GitUtils(listener, git).getRevisionForSHA1(git.revParse(HEAD));
  }
Ejemplo n.º 2
0
 private void insertChangeId(ObjectId treeId) throws IOException {
   ObjectId firstParentId = null;
   if (!parents.isEmpty()) firstParentId = parents.get(0);
   ObjectId changeId =
       ChangeIdUtil.computeChangeId(treeId, firstParentId, author, committer, message);
   message = ChangeIdUtil.insertId(message, changeId);
   if (changeId != null)
     message =
         message.replaceAll(
             "\nChange-Id: I" + ObjectId.zeroId().getName() + "\n",
             "\nChange-Id: I" + changeId.getName() + "\n");
 }
 private Git.Head getHead(final Repository repository) throws IOException {
   ObjectId revision = repository.resolve(Constants.HEAD);
   RevCommit commit = new RevWalk(repository).parseCommit(revision);
   Git.Head head =
       new Git.Head(
           revision.getName(),
           commit.getAuthorIdent().getName(),
           commit.getAuthorIdent().getEmailAddress(),
           commit.getCommitterIdent().getName(),
           commit.getCommitterIdent().getEmailAddress(),
           commit.getFullMessage());
   return head;
 }
Ejemplo n.º 4
0
  @Test
  public void test() throws Exception {

    GitService git = lookup(GitService.class);

    File gitDir = git.getWorkingDir();
    String tag = "mock-1.0" + System.currentTimeMillis();

    VersionContext context = new VersionContext(0, tag, "test", "test", "test");

    git.setup(context);
    git.pull(context);

    git.clearWorkingDir(context);

    downloadAndExtractTo(tag, gitDir);

    ObjectId objId = git.commit(context);
    git.push(context);

    Collection<Ref> refs = git.lsRemote();
    boolean tagExist = false;
    boolean commitSuccess = false;
    if (refs != null) {
      for (Ref ref : refs) {
        if (ref.getName().equals(REFS_TAGS + tag)) {
          tagExist = true;
        }
        if (ref.getObjectId().getName().equals(objId.getName())) {
          commitSuccess = true;
        }
      }
    }
    Assert.assertTrue(tagExist);
    Assert.assertTrue(commitSuccess);

    git.removeTag(context);

    refs = git.lsRemote();
    tagExist = false;
    if (refs != null) {
      for (Ref ref : refs) {
        if (ref.getName().equals(REFS_TAGS + tag)) {
          tagExist = true;
        }
      }
    }
    Assert.assertFalse(tagExist);
  }
 /**
  * Adds properties to the specified {@code transformer} for the current Git commit hash. The
  * following properties are added to {@code transformer}:
  *
  * <ul>
  *   <li>{@code repository.commit}: The full commit hash, in lowercase hexadecimal form.
  *   <li>{@code repository.commit.short}: The abbreviated commit hash, which is the first {@code
  *       abbrevLen} hexadecimal characters of the full commit hash.
  * </ul>
  *
  * <p>If {@code baseDir} is not currently stored in a Git repository, or if the current Git commit
  * hash could not be determined, this method logs a warning and returns {@code false}.
  *
  * @param transformer The transformer.
  * @param baseDir The base directory where versioned files are contained.
  * @param abbrevLen The length of the abbreviated commit hash to create, in number of hexadecimal
  *     characters.
  * @param log The Maven log instance.
  * @return {@code true} if the commit hash was identified and the properties added to the {@code
  *     transformer}; otherwise, {@code false}.
  */
 public static boolean addCommitProperties(
     Transformer transformer, File baseDir, int abbrevLen, Log log) {
   try {
     RepositoryBuilder builder = new RepositoryBuilder();
     Repository repository = builder.findGitDir(baseDir).readEnvironment().build();
     ObjectId objectId = repository.resolve(Constants.HEAD);
     if (objectId != null) {
       transformer.setParameter("repository.commit", objectId.getName());
       transformer.setParameter("repository.commit.short", objectId.abbreviate(abbrevLen).name());
       return true;
     } else {
       log.warn("Could not determine current repository commit hash.");
       return false;
     }
   } catch (IOException ex) {
     log.warn("Could not determine current repository commit hash.", ex);
     return false;
   }
 }
Ejemplo n.º 6
0
  private void assertReflog(ObjectId prevHead, ObjectId head) throws IOException {
    // Check the reflog for HEAD
    String actualHeadMessage = db.getReflogReader(Constants.HEAD).getLastEntry().getComment();
    String expectedHeadMessage = head.getName() + ": updating HEAD";
    assertEquals(expectedHeadMessage, actualHeadMessage);
    assertEquals(
        head.getName(), db.getReflogReader(Constants.HEAD).getLastEntry().getNewId().getName());
    assertEquals(
        prevHead.getName(), db.getReflogReader(Constants.HEAD).getLastEntry().getOldId().getName());

    // The reflog for master contains the same as the one for HEAD
    String actualMasterMessage =
        db.getReflogReader("refs/heads/master").getLastEntry().getComment();
    String expectedMasterMessage = head.getName() + ": updating HEAD"; // yes!
    assertEquals(expectedMasterMessage, actualMasterMessage);
    assertEquals(
        head.getName(), db.getReflogReader(Constants.HEAD).getLastEntry().getNewId().getName());
    assertEquals(
        prevHead.getName(),
        db.getReflogReader("refs/heads/master").getLastEntry().getOldId().getName());
  }
Ejemplo n.º 7
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();
      }
    }
  }
Ejemplo n.º 8
0
 public Object execute(ExecutionEvent event) throws ExecutionException {
   boolean compareMode =
       Boolean.TRUE.toString().equals(event.getParameter(HistoryViewCommands.COMPARE_MODE_PARAM));
   IStructuredSelection selection = getSelection(getPage());
   if (selection.size() < 1) return null;
   Object input = getPage().getInputInternal().getSingleFile();
   if (input == null) return null;
   IWorkbenchPage workBenchPage =
       HandlerUtil.getActiveWorkbenchWindowChecked(event).getActivePage();
   boolean errorOccurred = false;
   List<ObjectId> ids = new ArrayList<ObjectId>();
   String gitPath = null;
   if (input instanceof IFile) {
     IFile resource = (IFile) input;
     final RepositoryMapping map = RepositoryMapping.getMapping(resource);
     gitPath = map.getRepoRelativePath(resource);
     Iterator<?> it = selection.iterator();
     while (it.hasNext()) {
       RevCommit commit = (RevCommit) it.next();
       String commitPath = getRenamedPath(gitPath, commit);
       IFileRevision rev = null;
       try {
         rev = CompareUtils.getFileRevision(commitPath, commit, map.getRepository(), null);
       } catch (IOException e) {
         Activator.logError(
             NLS.bind(UIText.GitHistoryPage_errorLookingUpPath, gitPath, commit.getId()), e);
         errorOccurred = true;
       }
       if (rev != null) {
         if (compareMode) {
           ITypedElement right =
               CompareUtils.getFileRevisionTypedElement(commitPath, commit, map.getRepository());
           final GitCompareFileRevisionEditorInput in =
               new GitCompareFileRevisionEditorInput(
                   SaveableCompareEditorInput.createFileElement(resource), right, null);
           try {
             CompareUtils.openInCompare(workBenchPage, in);
           } catch (Exception e) {
             errorOccurred = true;
           }
         } else
           try {
             EgitUiEditorUtils.openEditor(
                 getPart(event).getSite().getPage(), rev, new NullProgressMonitor());
           } catch (CoreException e) {
             Activator.logError(UIText.GitHistoryPage_openFailed, e);
             errorOccurred = true;
           }
       } else ids.add(commit.getId());
     }
   }
   if (input instanceof File) {
     File fileInput = (File) input;
     Repository repo = getRepository(event);
     gitPath = getRepoRelativePath(repo, fileInput);
     Iterator<?> it = selection.iterator();
     while (it.hasNext()) {
       RevCommit commit = (RevCommit) it.next();
       String commitPath = getRenamedPath(gitPath, commit);
       IFileRevision rev = null;
       try {
         rev = CompareUtils.getFileRevision(commitPath, commit, repo, null);
       } catch (IOException e) {
         Activator.logError(
             NLS.bind(UIText.GitHistoryPage_errorLookingUpPath, commitPath, commit.getId()), e);
         errorOccurred = true;
       }
       if (rev != null) {
         if (compareMode)
           try {
             ITypedElement left =
                 CompareUtils.getFileRevisionTypedElement(
                     gitPath, new RevWalk(repo).parseCommit(repo.resolve(Constants.HEAD)), repo);
             ITypedElement right =
                 CompareUtils.getFileRevisionTypedElement(commitPath, commit, repo);
             final GitCompareFileRevisionEditorInput in =
                 new GitCompareFileRevisionEditorInput(left, right, null);
             CompareUtils.openInCompare(workBenchPage, in);
           } catch (IOException e) {
             errorOccurred = true;
           }
         else
           try {
             EgitUiEditorUtils.openEditor(
                 getPart(event).getSite().getPage(), rev, new NullProgressMonitor());
           } catch (CoreException e) {
             Activator.logError(UIText.GitHistoryPage_openFailed, e);
             errorOccurred = true;
           }
       } else ids.add(commit.getId());
     }
   }
   if (errorOccurred) Activator.showError(UIText.GitHistoryPage_openFailed, null);
   if (ids.size() > 0) {
     StringBuilder idList = new StringBuilder(""); // $NON-NLS-1$
     for (ObjectId objectId : ids) idList.append(objectId.getName()).append(' ');
     MessageDialog.openError(
         getPart(event).getSite().getShell(),
         UIText.GitHistoryPage_fileNotFound,
         NLS.bind(UIText.GitHistoryPage_notContainedInCommits, gitPath, idList.toString()));
   }
   return null;
 }
Ejemplo n.º 9
0
  protected void addInformationForPath(
      Repository repository,
      Git git,
      DocumentWriter writer,
      RevCommit commit,
      String path,
      CallSpecification spec,
      Values values)
      throws GitAPIException, IOException {
    // Make sure the path is in the canonical form we need ...
    if (path.startsWith("/")) {
      if (path.length() == 1) path = "";
      else path = path.substring(1);
    }

    // Now see if we're actually referring to the "jcr:content" node ...
    boolean isContentNode = false;
    if (path.endsWith(JCR_CONTENT_SUFFIX)) {
      isContentNode = true;
      path = path.substring(0, path.length() - JCR_CONTENT_SUFFIX.length());
    }

    // Create the TreeWalk that we'll use to navigate the files/directories ...
    final TreeWalk tw = new TreeWalk(repository);
    tw.addTree(commit.getTree());
    if ("".equals(path)) {
      // This is the top-level directory, so we don't need to pre-walk to find anything ...
      tw.setRecursive(false);
      while (tw.next()) {
        String childName = tw.getNameString();
        String childId = spec.childId(childName);
        writer.addChild(childId, childName);
      }
    } else {
      // We need to first find our path *before* we can walk the children ...
      PathFilter filter = PathFilter.create(path);
      tw.setFilter(filter);
      while (tw.next()) {
        if (filter.isDone(tw)) {
          break;
        } else if (tw.isSubtree()) {
          tw.enterSubtree();
        }
      }
      // Now that the TreeWalk is the in right location given by the 'path', we can get the
      if (tw.isSubtree()) {
        // The object at the 'path' is a directory, so go into it ...
        tw.enterSubtree();

        // Find the commit in which this folder was last modified ...
        // This may not be terribly efficient, but it seems to work faster on subsequent runs ...
        RevCommit folderCommit = git.log().addPath(path).call().iterator().next();

        // Add folder-related properties ...
        String committer = folderCommit.getCommitterIdent().getName();
        String author = folderCommit.getAuthorIdent().getName();
        DateTime committed = values.dateFrom(folderCommit.getCommitTime());
        writer.setPrimaryType(GitLexicon.FOLDER);
        writer.addProperty(JcrLexicon.CREATED, committed);
        writer.addProperty(JcrLexicon.CREATED_BY, committer);
        writer.addProperty(GitLexicon.OBJECT_ID, folderCommit.getId().name());
        writer.addProperty(GitLexicon.AUTHOR, author);
        writer.addProperty(GitLexicon.COMMITTER, committer);
        writer.addProperty(GitLexicon.COMMITTED, committed);
        writer.addProperty(GitLexicon.TITLE, folderCommit.getShortMessage());

        // And now walk the contents of the directory ...
        while (tw.next()) {
          String childName = tw.getNameString();
          String childId = spec.childId(childName);
          writer.addChild(childId, childName);
        }
      } else {
        // The path specifies a file (or a content node) ...

        // Find the commit in which this folder was last modified ...
        // This may not be terribly efficient, but it seems to work faster on subsequent runs ...
        RevCommit fileCommit = git.log().addPath(path).call().iterator().next();

        // Add file-related properties ...
        String committer = fileCommit.getCommitterIdent().getName();
        String author = fileCommit.getAuthorIdent().getName();
        DateTime committed = values.dateFrom(fileCommit.getCommitTime());
        if (isContentNode) {
          writer.setPrimaryType(GitLexicon.RESOURCE);
          writer.addProperty(JcrLexicon.LAST_MODIFIED, committed);
          writer.addProperty(JcrLexicon.LAST_MODIFIED_BY, committer);
          writer.addProperty(GitLexicon.OBJECT_ID, fileCommit.getId().name());
          writer.addProperty(GitLexicon.AUTHOR, author);
          writer.addProperty(GitLexicon.COMMITTER, committer);
          writer.addProperty(GitLexicon.COMMITTED, committed);
          writer.addProperty(GitLexicon.TITLE, fileCommit.getShortMessage());
          // Create the BinaryValue ...
          ObjectId fileObjectId = tw.getObjectId(0);
          ObjectLoader fileLoader = repository.open(fileObjectId);
          BinaryKey key = new BinaryKey(fileObjectId.getName());
          BinaryValue value = values.binaryFor(key, fileLoader.getSize());
          if (value == null) {
            // It wasn't found in the binary store ...
            if (fileLoader.isLarge()) {
              // Too large to hold in memory, so use the binary store (which reads the file
              // immediately) ...
              value = values.binaryFrom(fileLoader.openStream());
            } else {
              // This is small enough to fit into a byte[], but it still may be pretty big ...
              value =
                  new GitBinaryValue(
                      fileObjectId,
                      fileLoader,
                      connector.getSourceName(),
                      name,
                      connector.getMimeTypeDetector());
            }
          }
          writer.addProperty(JcrLexicon.DATA, value);
          if (connector.includeMimeType()) {
            try {
              String filename =
                  spec.parameter(spec.parameterCount() - 1); // the last is 'jcr:content'
              String mimeType = value.getMimeType(filename);
              if (mimeType != null) writer.addProperty(JcrLexicon.MIMETYPE, mimeType);
            } catch (RepositoryException e) {
              // do nothing
            } catch (IOException e) {
              // do nothing
            }
          }
        } else {
          writer.setPrimaryType(GitLexicon.FILE);
          writer.addProperty(JcrLexicon.CREATED, committed);
          writer.addProperty(JcrLexicon.CREATED_BY, committer);
          writer.addProperty(GitLexicon.OBJECT_ID, fileCommit.getId().name());
          writer.addProperty(GitLexicon.AUTHOR, author);
          writer.addProperty(GitLexicon.COMMITTER, committer);
          writer.addProperty(GitLexicon.COMMITTED, committed);
          writer.addProperty(GitLexicon.TITLE, fileCommit.getShortMessage());

          // Add the "jcr:content" child node ...
          String childId = spec.childId(JCR_CONTENT);
          writer.addChild(childId, JCR_CONTENT);
        }
      }
    }
  }