@Override
 public Object apply(FileResource resource, Input input) throws OrmException {
   ReviewDb db = dbProvider.get();
   AccountPatchReview apr = getExisting(db, resource);
   if (apr != null) {
     db.accountPatchReviews().delete(Collections.singleton(apr));
   }
   return Response.none();
 }
 @Override
 public List<Change> load(Project.NameKey key) throws Exception {
   final ReviewDb db = schema.open();
   try {
     return Collections.unmodifiableList(db.changes().byProject(key).toList());
   } finally {
     db.close();
   }
 }
Beispiel #3
0
  private long addAccountAgreements(
      ReviewDb db,
      ProjectConfig config,
      List<AccountGroup.UUID> adminGroupUUIDs,
      Map<Integer, ContributorAgreement> agreements)
      throws SQLException, OrmException {
    Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
    try {
      ResultSet rs =
          stmt.executeQuery(
              "SELECT account_id, cla_id, accepted_on, reviewed_by,"
                  + "       reviewed_on, review_comments "
                  + "FROM account_agreements WHERE status = 'V'");
      try {
        long minTime = TimeUtil.nowMs();
        while (rs.next()) {
          Account.Id accountId = new Account.Id(rs.getInt(1));
          Account.Id reviewerId = new Account.Id(rs.getInt(4));
          if (rs.wasNull()) {
            reviewerId = accountId;
          }

          int claId = rs.getInt(2);
          ContributorAgreement agreement = agreements.get(claId);
          if (agreement == null) {
            continue; // Agreement is invalid
          }

          Timestamp acceptedOn = rs.getTimestamp(3);
          minTime = Math.min(minTime, acceptedOn.getTime());

          // Enter Agreement
          GroupReference individualGroup =
              getOrCreateGroupForIndividuals(db, config, adminGroupUUIDs, agreement);
          AccountGroup.Id groupId =
              db.accountGroups().byUUID(individualGroup.getUUID()).toList().get(0).getId();

          final AccountGroupMember.Key key = new AccountGroupMember.Key(accountId, groupId);
          AccountGroupMember m = db.accountGroupMembers().get(key);
          if (m == null) {
            m = new AccountGroupMember(key);
            db.accountGroupMembersAudit()
                .insert(
                    Collections.singleton(new AccountGroupMemberAudit(m, reviewerId, acceptedOn)));
            db.accountGroupMembers().insert(Collections.singleton(m));
          }
        }
        return minTime;
      } finally {
        rs.close();
      }
    } finally {
      stmt.close();
    }
  }
Beispiel #4
0
  private void setMerged(Change c, ChangeMessage msg, ObjectId mergeResultRev)
      throws OrmException, IOException {
    logDebug("Setting change {} merged", c.getId());
    ChangeUpdate update = null;
    final PatchSetApproval submitter;
    PatchSet merged;
    try {
      db.changes().beginTransaction(c.getId());

      // We must pull the patchset out of commits, because the patchset ID is
      // modified when using the cherry-pick merge strategy.
      CodeReviewCommit commit = commits.get(c.getId());
      PatchSet.Id mergedId = commit.change().currentPatchSetId();
      merged = db.patchSets().get(mergedId);
      c = setMergedPatchSet(c.getId(), mergedId);
      submitter = approvalsUtil.getSubmitter(db, commit.notes(), mergedId);
      ChangeControl control = commit.getControl();
      update = updateFactory.create(control, c.getLastUpdatedOn());

      // TODO(yyonas): we need to be able to change the author of the message
      // is not the person for whom the change was made. addMergedMessage
      // did this in the past.
      if (msg != null) {
        cmUtil.addChangeMessage(db, update, msg);
      }
      db.commit();

    } finally {
      db.rollback();
    }
    update.commit();
    indexer.index(db, c);

    try {
      mergedSenderFactory
          .create(c.getId(), submitter != null ? submitter.getAccountId() : null)
          .sendAsync();
    } catch (Exception e) {
      log.error("Cannot email merged notification for " + c.getId(), e);
    }
    if (submitter != null && mergeResultRev != null) {
      try {
        hooks.doChangeMergedHook(
            c,
            accountCache.get(submitter.getAccountId()).getAccount(),
            merged,
            db,
            mergeResultRev.name());
      } catch (OrmException ex) {
        logError("Cannot run hook for submitted patch set " + c.getId(), ex);
      }
    }
  }
 @Override
 public Object apply(FileResource resource, Input input) throws OrmException {
   ReviewDb db = dbProvider.get();
   AccountPatchReview apr = getExisting(db, resource);
   if (apr == null) {
     db.accountPatchReviews()
         .insert(
             Collections.singleton(
                 new AccountPatchReview(resource.getPatchKey(), resource.getAccountId())));
     return Response.created("");
   } else {
     return Response.ok("");
   }
 }
  private String format(final Account account, final ContactInformation info)
      throws ContactInformationStoreException {
    Timestamp on = account.getContactFiledOn();
    if (on == null) {
      on = new Timestamp(System.currentTimeMillis());
    }

    final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    df.setTimeZone(UTC);

    final StringBuilder b = new StringBuilder();
    field(b, "Account-Id", account.getId().toString());
    field(b, "Date", df.format(on) + " " + UTC.getID());
    field(b, "Full-Name", account.getFullName());
    field(b, "Preferred-Email", account.getPreferredEmail());

    try {
      final ReviewDb db = schema.open();
      try {
        for (final AccountExternalId e : db.accountExternalIds().byAccount(account.getId())) {
          final StringBuilder oistr = new StringBuilder();
          if (e.getEmailAddress() != null && e.getEmailAddress().length() > 0) {
            if (oistr.length() > 0) {
              oistr.append(' ');
            }
            oistr.append(e.getEmailAddress());
          }
          if (e.isScheme(AccountExternalId.SCHEME_MAILTO)) {
            if (oistr.length() > 0) {
              oistr.append(' ');
            }
            oistr.append('<');
            oistr.append(e.getExternalId());
            oistr.append('>');
          }
          field(b, "Identity", oistr.toString());
        }
      } finally {
        db.close();
      }
    } catch (OrmException e) {
      throw new ContactInformationStoreException(e);
    }

    field(b, "Address", info.getAddress());
    field(b, "Country", info.getCountry());
    field(b, "Phone-Number", info.getPhoneNumber());
    field(b, "Fax-Number", info.getFaxNumber());
    return b.toString();
  }
Beispiel #7
0
  private GroupReference getOrCreateGroupForIndividuals(
      ReviewDb db,
      ProjectConfig config,
      List<AccountGroup.UUID> adminGroupUUIDs,
      ContributorAgreement agreement)
      throws OrmException {
    if (!agreement.getAccepted().isEmpty()) {
      return agreement.getAccepted().get(0).getGroup();
    }

    String name = "CLA Accepted - " + agreement.getName();
    AccountGroupName agn = db.accountGroupNames().get(new AccountGroup.NameKey(name));
    AccountGroup ag;
    if (agn != null) {
      ag = db.accountGroups().get(agn.getId());
      if (ag == null) {
        throw new IllegalStateException(
            "account group name exists but account group does not: " + name);
      }

      if (!adminGroupUUIDs.contains(ag.getOwnerGroupUUID())) {
        throw new IllegalStateException(
            "individual group exists with non admin owner group: " + name);
      }
    } else {
      ag =
          createGroup(
              db,
              name,
              adminGroupUUIDs.get(0),
              String.format("Users who have accepted the %s CLA", agreement.getName()));
    }
    GroupReference group = config.resolve(ag);
    agreement.setAccepted(Lists.newArrayList(new PermissionRule(group)));
    if (agreement.getAutoVerify() != null) {
      agreement.setAutoVerify(group);
    }

    // Don't allow accounts in the same individual CLA group to see each
    // other in same group visibility mode.
    List<PermissionRule> sameGroupVisibility = config.getAccountsSection().getSameGroupVisibility();
    PermissionRule rule = new PermissionRule(group);
    rule.setDeny();
    if (!sameGroupVisibility.contains(rule)) {
      sameGroupVisibility.add(rule);
    }
    return group;
  }
  private Iterable<ChangeData> byCommitsOnBranchNotMergedFromDatabase(
      Repository repo, ReviewDb db, Branch.NameKey branch, List<String> hashes)
      throws OrmException, IOException {
    Set<Change.Id> changeIds = Sets.newHashSetWithExpectedSize(hashes.size());
    String lastPrefix = null;
    for (Ref ref : repo.getRefDatabase().getRefs(RefNames.REFS_CHANGES).values()) {
      String r = ref.getName();
      if ((lastPrefix != null && r.startsWith(lastPrefix))
          || !hashes.contains(ref.getObjectId().name())) {
        continue;
      }
      Change.Id id = Change.Id.fromRef(r);
      if (id == null) {
        continue;
      }
      if (changeIds.add(id)) {
        lastPrefix = r.substring(0, r.lastIndexOf('/'));
      }
    }

    List<ChangeData> cds = new ArrayList<>(hashes.size());
    for (Change c : db.changes().get(changeIds)) {
      if (c.getDest().equals(branch) && c.getStatus() != Change.Status.MERGED) {
        cds.add(changeDataFactory.create(db, c));
      }
    }
    return cds;
  }
Beispiel #9
0
  protected void updateSuperProjects(ReviewDb db, Set<Branch.NameKey> updatedBranches)
      throws SubmoduleException {
    try {
      // These (repo/branch) will be updated later with all the given
      // individual submodule subscriptions
      Multimap<Branch.NameKey, SubmoduleSubscription> targets = HashMultimap.create();

      for (Branch.NameKey updatedBranch : updatedBranches) {
        for (SubmoduleSubscription sub : db.submoduleSubscriptions().bySubmodule(updatedBranch)) {
          targets.put(sub.getSuperProject(), sub);
        }
      }
      updatedSubscribers.addAll(updatedBranches);
      // Update subscribers.
      for (Branch.NameKey dest : targets.keySet()) {
        try {
          if (!updatedSubscribers.add(dest)) {
            log.error("Possible circular subscription involving " + dest);
          } else {
            updateGitlinks(db, dest, targets.get(dest));
          }
        } catch (SubmoduleException e) {
          log.warn("Cannot update gitlinks for " + dest, e);
        }
      }
    } catch (OrmException e) {
      logAndThrowSubmoduleException("Cannot read subscription records", e);
    }
  }
Beispiel #10
0
 private AccountGroup createGroup(
     ReviewDb db, String groupName, AccountGroup.UUID adminGroupUUID, String description)
     throws OrmException {
   final AccountGroup.Id groupId = new AccountGroup.Id(db.nextAccountGroupId());
   final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(groupName);
   final AccountGroup.UUID uuid = GroupUUID.make(groupName, serverUser);
   final AccountGroup group = new AccountGroup(nameKey, groupId, uuid);
   group.setOwnerGroupUUID(adminGroupUUID);
   group.setDescription(description);
   final AccountGroupName gn = new AccountGroupName(group);
   // first insert the group name to validate that the group name hasn't
   // already been used to create another group
   db.accountGroupNames().insert(Collections.singleton(gn));
   db.accountGroups().insert(Collections.singleton(group));
   return group;
 }
Beispiel #11
0
 private Change setMergedPatchSet(Change.Id changeId, final PatchSet.Id merged)
     throws OrmException {
   return db.changes()
       .atomicUpdate(
           changeId,
           new AtomicUpdate<Change>() {
             @Override
             public Change update(Change c) {
               c.setStatus(Change.Status.MERGED);
               c.setSubmissionId(submissionId);
               if (!merged.equals(c.currentPatchSetId())) {
                 // Uncool; the patch set changed after we merged it.
                 // Go back to the patch set that was actually merged.
                 //
                 try {
                   c.setCurrentPatchSet(patchSetInfoFactory.get(db, merged));
                 } catch (PatchSetInfoNotAvailableException e1) {
                   logError("Cannot read merged patch set " + merged, e1);
                 }
               }
               ChangeUtil.updated(c);
               return c;
             }
           });
 }
  @Before
  public void setUpInjector() throws Exception {
    lifecycle = new LifecycleManager();
    Injector injector = createInjector();
    lifecycle.add(injector);
    injector.injectMembers(this);
    lifecycle.start();

    db = schemaFactory.open();
    schemaCreator.create(db);
    userId = accountManager.authenticate(AuthRequest.forUser("user")).getAccountId();
    Account userAccount = db.accounts().get(userId);
    userAccount.setPreferredEmail("*****@*****.**");
    db.accounts().update(ImmutableList.of(userAccount));
    user = userFactory.create(Providers.of(db), userId);
    requestContext.setContext(newRequestContext(userAccount.getId()));
  }
Beispiel #13
0
 private void matchChange(Set<Change.Id> matched, Change.Id changeId) {
   if (changeId != null && !matched.contains(changeId)) {
     try {
       matchChange(matched, db.changes().get(changeId));
     } catch (OrmException e) {
       log.warn("Error reading change " + changeId, e);
     }
   }
 }
Beispiel #14
0
  private void abandonOneChange(Change change)
      throws OrmException, NoSuchChangeException, IOException {
    db.changes().beginTransaction(change.getId());

    // TODO(dborowitz): support InternalUser in ChangeUpdate
    ChangeControl control =
        changeControlFactory.controlFor(change, identifiedUserFactory.create(change.getOwner()));
    ChangeUpdate update = updateFactory.create(control);
    try {
      change =
          db.changes()
              .atomicUpdate(
                  change.getId(),
                  new AtomicUpdate<Change>() {
                    @Override
                    public Change update(Change change) {
                      if (change.getStatus().isOpen()) {
                        change.setStatus(Change.Status.ABANDONED);
                        return change;
                      }
                      return null;
                    }
                  });

      if (change != null) {
        ChangeMessage msg =
            new ChangeMessage(
                new ChangeMessage.Key(change.getId(), ChangeUtil.messageUUID(db)),
                null,
                change.getLastUpdatedOn(),
                change.currentPatchSetId());
        msg.setMessage("Project was deleted.");

        // TODO(yyonas): atomic change is not propagated.
        cmUtil.addChangeMessage(db, update, msg);
        db.commit();
        indexer.index(db, change);
      }
    } finally {
      db.rollback();
    }
    update.commit();
  }
 @After
 public void tearDownInjector() {
   if (lifecycle != null) {
     lifecycle.stop();
   }
   requestContext.setContext(null);
   if (db != null) {
     db.close();
   }
   InMemoryDatabase.drop(schemaFactory);
 }
Beispiel #16
0
  @Override
  public void postRun() throws Exception {
    AuthType authType = flags.cfg.getEnum(AuthType.values(), "auth", null, "type", null);
    if (authType != AuthType.DEVELOPMENT_BECOME_ANY_ACCOUNT) {
      return;
    }

    try (ReviewDb db = dbFactory.open()) {
      if (db.accounts().anyAccounts().toList().isEmpty()) {
        ui.header("Gerrit Administrator");
        if (ui.yesno(true, "Create administrator user")) {
          Account.Id id = new Account.Id(db.nextAccountId());
          String username = ui.readString("admin", "username");
          String name = ui.readString("Administrator", "name");
          String httpPassword = ui.readString("secret", "HTTP password");
          AccountSshKey sshKey = readSshKey(id);
          String email = readEmail(sshKey);

          AccountExternalId extUser =
              new AccountExternalId(
                  id, new AccountExternalId.Key(AccountExternalId.SCHEME_USERNAME, username));
          if (!Strings.isNullOrEmpty(httpPassword)) {
            extUser.setPassword(httpPassword);
          }
          db.accountExternalIds().insert(Collections.singleton(extUser));

          if (email != null) {
            AccountExternalId extMailto =
                new AccountExternalId(
                    id, new AccountExternalId.Key(AccountExternalId.SCHEME_MAILTO, email));
            extMailto.setEmailAddress(email);
            db.accountExternalIds().insert(Collections.singleton(extMailto));
          }

          Account a = new Account(id, TimeUtil.nowTs());
          a.setFullName(name);
          a.setPreferredEmail(email);
          db.accounts().insert(Collections.singleton(a));

          AccountGroupMember m =
              new AccountGroupMember(new AccountGroupMember.Key(id, new AccountGroup.Id(1)));
          db.accountGroupMembers().insert(Collections.singleton(m));

          if (sshKey != null) {
            db.accountSshKeys().insert(Collections.singleton(sshKey));
          }
        }
      }
    }
  }
Beispiel #17
0
  private void setApproval(ChangeData cd, IdentifiedUser user) throws OrmException, IOException {
    Timestamp timestamp = TimeUtil.nowTs();
    ChangeControl control = cd.changeControl();
    PatchSet.Id psId = cd.currentPatchSet().getId();
    PatchSet.Id psIdNewRev = commits.get(cd.change().getId()).change().currentPatchSetId();

    logDebug("Add approval for " + cd + " from user " + user);
    ChangeUpdate update = updateFactory.create(control, timestamp);
    update.putReviewer(user.getAccountId(), REVIEWER);
    List<SubmitRecord> record = records.get(cd.change().getId());
    if (record != null) {
      update.merge(record);
    }
    db.changes().beginTransaction(cd.change().getId());
    try {
      BatchMetaDataUpdate batch = approve(control, psId, user, update, timestamp);
      batch.write(update, new CommitBuilder());

      // If the submit strategy created a new revision (rebase, cherry-pick)
      // approve that as well
      if (!psIdNewRev.equals(psId)) {
        update.setPatchSetId(psId);
        update.commit();
        // Create a new ChangeUpdate instance because we need to store meta data
        // on another patch set (psIdNewRev).
        update = updateFactory.create(control, timestamp);
        batch = approve(control, psIdNewRev, user, update, timestamp);
        // Write update commit after all normalized label commits.
        batch.write(update, new CommitBuilder());
      }
      db.commit();
    } finally {
      db.rollback();
    }
    update.commit();
    indexer.index(db, cd.change());
  }
Beispiel #18
0
  private BatchMetaDataUpdate approve(
      ChangeControl control,
      PatchSet.Id psId,
      IdentifiedUser user,
      ChangeUpdate update,
      Timestamp timestamp)
      throws OrmException {
    Map<PatchSetApproval.Key, PatchSetApproval> byKey = Maps.newHashMap();
    for (PatchSetApproval psa : approvalsUtil.byPatchSet(db, control, psId)) {
      if (!byKey.containsKey(psa.getKey())) {
        byKey.put(psa.getKey(), psa);
      }
    }

    PatchSetApproval submit =
        new PatchSetApproval(
            new PatchSetApproval.Key(psId, user.getAccountId(), LabelId.SUBMIT),
            (short) 1,
            TimeUtil.nowTs());
    byKey.put(submit.getKey(), submit);
    submit.setValue((short) 1);
    submit.setGranted(timestamp);

    // Flatten out existing approvals for this patch set based upon the current
    // permissions. Once the change is closed the approvals are not updated at
    // presentation view time, except for zero votes used to indicate a reviewer
    // was added. So we need to make sure votes are accurate now. This way if
    // permissions get modified in the future, historical records stay accurate.
    LabelNormalizer.Result normalized = labelNormalizer.normalize(control, byKey.values());

    // TODO(dborowitz): Don't use a label in notedb; just check when status
    // change happened.
    update.putApproval(submit.getLabel(), submit.getValue());
    logDebug("Adding submit label " + submit);

    db.patchSetApprovals().upsert(normalized.getNormalized());
    db.patchSetApprovals().delete(normalized.deleted());

    try {
      return saveToBatch(control, update, normalized, timestamp);
    } catch (IOException e) {
      throw new OrmException(e);
    }
  }
  protected ChangeInserter newChange(
      TestRepository<Repo> repo,
      @Nullable RevCommit commit,
      @Nullable String key,
      @Nullable Integer owner,
      @Nullable String branch)
      throws Exception {
    if (commit == null) {
      commit = repo.parseBody(repo.commit().message("message").create());
    }
    Account.Id ownerId = owner != null ? new Account.Id(owner) : userId;
    branch = MoreObjects.firstNonNull(branch, "refs/heads/master");
    if (!branch.startsWith("refs/heads/")) {
      branch = "refs/heads/" + branch;
    }
    Project.NameKey project =
        new Project.NameKey(repo.getRepository().getDescription().getRepositoryName());

    Change.Id id = new Change.Id(db.nextChangeId());
    if (key == null) {
      key =
          "I"
              + Hashing.sha1()
                  .newHasher()
                  .putInt(id.get())
                  .putString(project.get(), UTF_8)
                  .putString(commit.name(), UTF_8)
                  .putInt(ownerId.get())
                  .putString(branch, UTF_8)
                  .hash()
                  .toString();
    }

    Change change =
        new Change(
            new Change.Key(key),
            id,
            ownerId,
            new Branch.NameKey(project, branch),
            TimeUtil.nowTs());
    IdentifiedUser user = userFactory.create(Providers.of(db), ownerId);
    return changeFactory.create(projectControlFactory.controlFor(project, user), change, commit);
  }
  @Test
  public void updatedOrderWithSubMinuteResolution() throws Exception {
    TestRepository<Repo> repo = createProject("repo");
    ChangeInserter ins1 = newChange(repo, null, null, null, null);
    Change change1 = ins1.insert();
    Change change2 = newChange(repo, null, null, null, null).insert();

    assertThat(lastUpdatedMs(change1)).isLessThan(lastUpdatedMs(change2));

    assertQuery("status:new", change2, change1);

    gApi.changes().id(change1.getId().get()).current().review(new ReviewInput());
    change1 = db.changes().get(change1.getId());

    assertThat(lastUpdatedMs(change1)).isGreaterThan(lastUpdatedMs(change2));
    assertThat(lastUpdatedMs(change1) - lastUpdatedMs(change2))
        .isLessThan(MILLISECONDS.convert(1, MINUTES));

    // change1 moved to the top.
    assertQuery("status:new", change1, change2);
  }
Beispiel #21
0
 /** Mark the current schema version. */
 protected void finish(CurrentSchemaVersion curr, ReviewDb db) throws OrmException {
   curr.versionNbr = versionNbr;
   db.schemaVersion().update(Collections.singleton(curr));
 }
Beispiel #22
0
  @Override
  protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
    Repository git;
    try {
      git = mgr.openRepository(allProjects);
    } catch (IOException e) {
      throw new OrmException(e);
    }
    try {
      MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjects, git);
      ProjectConfig config = ProjectConfig.read(md);
      Map<Integer, ContributorAgreement> agreements = getAgreementToAdd(db, config);
      if (agreements.isEmpty()) {
        return;
      }
      ui.message("Moved contributor agreements to project.config");

      // Create the auto verify groups.
      List<AccountGroup.UUID> adminGroupUUIDs = getAdministrateServerGroups(db, config);
      for (ContributorAgreement agreement : agreements.values()) {
        if (agreement.getAutoVerify() != null) {
          getOrCreateGroupForIndividuals(db, config, adminGroupUUIDs, agreement);
        }
      }

      // Scan AccountAgreement
      long minTime = addAccountAgreements(db, config, adminGroupUUIDs, agreements);

      ProjectConfig base = ProjectConfig.read(md, null);
      for (ContributorAgreement agreement : agreements.values()) {
        base.replace(agreement);
      }
      base.getAccountsSection()
          .setSameGroupVisibility(config.getAccountsSection().getSameGroupVisibility());

      BatchMetaDataUpdate batch = base.openUpdate(md);
      try {
        // Scan AccountGroupAgreement
        List<AccountGroupAgreement> groupAgreements = getAccountGroupAgreements(db, agreements);

        // Find the earliest change
        for (AccountGroupAgreement aga : groupAgreements) {
          minTime = Math.min(minTime, aga.getTime());
        }
        minTime -= 60 * 1000; // 1 Minute

        CommitBuilder commit = new CommitBuilder();
        commit.setAuthor(new PersonIdent(serverUser, new Date(minTime)));
        commit.setCommitter(new PersonIdent(serverUser, new Date(minTime)));
        commit.setMessage(
            "Add the ContributorAgreements for upgrade to Gerrit Code Review schema 65\n");
        batch.write(commit);

        for (AccountGroupAgreement aga : groupAgreements) {
          AccountGroup group = db.accountGroups().get(aga.groupId);
          if (group == null) {
            continue;
          }

          ContributorAgreement agreement = agreements.get(aga.claId);
          agreement.getAccepted().add(new PermissionRule(config.resolve(group)));
          base.replace(agreement);

          PersonIdent ident = null;
          if (aga.reviewedBy != null) {
            Account ua = db.accounts().get(aga.reviewedBy);
            if (ua != null) {
              String name = ua.getFullName();
              String email = ua.getPreferredEmail();

              if (email == null || email.isEmpty()) {
                // No preferred email is configured. Use a generic identity so we
                // don't leak an address the user may have given us, but doesn't
                // necessarily want to publish through Git records.
                //
                String user = ua.getUserName();
                if (user == null || user.isEmpty()) {
                  user = "******" + ua.getId().toString();
                }

                String host = SystemReader.getInstance().getHostname();
                email = user + "@" + host;
              }

              if (name == null || name.isEmpty()) {
                final int at = email.indexOf('@');
                if (0 < at) {
                  name = email.substring(0, at);
                } else {
                  name = anonymousCowardName;
                }
              }

              ident = new PersonIdent(name, email, new Date(aga.getTime()), TimeZone.getDefault());
            }
          }
          if (ident == null) {
            ident = new PersonIdent(serverUser, new Date(aga.getTime()));
          }

          // Build the commits such that it keeps track of the date added and
          // who added it.
          commit = new CommitBuilder();
          commit.setAuthor(ident);
          commit.setCommitter(new PersonIdent(serverUser, new Date(aga.getTime())));

          String msg =
              String.format(
                  "Accept %s contributor agreement for %s\n", agreement.getName(), group.getName());
          if (!Strings.isNullOrEmpty(aga.reviewComments)) {
            msg += "\n" + aga.reviewComments + "\n";
          }
          commit.setMessage(msg);
          batch.write(commit);
        }

        // Merge the agreements with the other data in project.config.
        commit = new CommitBuilder();
        commit.setAuthor(serverUser);
        commit.setCommitter(serverUser);
        commit.setMessage("Upgrade to Gerrit Code Review schema 65\n");
        commit.addParentId(config.getRevision());
        batch.write(config, commit);

        // Save the the final metadata.
        batch.commitAt(config.getRevision());
      } finally {
        batch.close();
      }
    } catch (IOException e) {
      throw new OrmException(e);
    } catch (ConfigInvalidException e) {
      throw new OrmException(e);
    } finally {
      git.close();
    }
  }
Beispiel #23
0
  void updateSubmoduleSubscriptions(ReviewDb db, Branch.NameKey destBranch)
      throws SubmoduleException {
    if (urlProvider.get() == null) {
      logAndThrowSubmoduleException(
          "Cannot establish canonical web url used "
              + "to access gerrit. It should be provided in gerrit.config file.");
    }
    try (Repository repo = repoManager.openRepository(destBranch.getParentKey());
        RevWalk rw = new RevWalk(repo)) {

      ObjectId id = repo.resolve(destBranch.get());
      RevCommit commit = rw.parseCommit(id);

      Set<SubmoduleSubscription> oldSubscriptions =
          Sets.newHashSet(db.submoduleSubscriptions().bySuperProject(destBranch));

      Set<SubmoduleSubscription> newSubscriptions;
      TreeWalk tw = TreeWalk.forPath(repo, GIT_MODULES, commit.getTree());
      if (tw != null
          && (FileMode.REGULAR_FILE.equals(tw.getRawMode(0))
              || FileMode.EXECUTABLE_FILE.equals(tw.getRawMode(0)))) {
        BlobBasedConfig bbc = new BlobBasedConfig(null, repo, commit, GIT_MODULES);

        String thisServer = new URI(urlProvider.get()).getHost();

        newSubscriptions =
            subSecParserFactory.create(bbc, thisServer, destBranch).parseAllSections();
      } else {
        newSubscriptions = Collections.emptySet();
      }

      Set<SubmoduleSubscription> alreadySubscribeds = new HashSet<>();
      for (SubmoduleSubscription s : newSubscriptions) {
        if (oldSubscriptions.contains(s)) {
          alreadySubscribeds.add(s);
        }
      }

      oldSubscriptions.removeAll(newSubscriptions);
      newSubscriptions.removeAll(alreadySubscribeds);

      if (!oldSubscriptions.isEmpty()) {
        db.submoduleSubscriptions().delete(oldSubscriptions);
      }
      if (!newSubscriptions.isEmpty()) {
        db.submoduleSubscriptions().insert(newSubscriptions);
      }

    } catch (OrmException e) {
      logAndThrowSubmoduleException(
          "Database problem at update of subscriptions table from " + GIT_MODULES + " file.", e);
    } catch (ConfigInvalidException e) {
      logAndThrowSubmoduleException(
          "Problem at update of subscriptions table: " + GIT_MODULES + " config file is invalid.",
          e);
    } catch (IOException e) {
      logAndThrowSubmoduleException(
          "Problem at update of subscriptions table from " + GIT_MODULES + ".", e);
    } catch (URISyntaxException e) {
      logAndThrowSubmoduleException(
          "Incorrect gerrit canonical web url provided in gerrit.config file.", e);
    }
  }
Beispiel #24
0
  private Set<Change.Id> parseChangeId(String idstr) throws UnloggedFailure, OrmException {
    Set<Change.Id> matched = new HashSet<>(4);
    boolean isCommit = idstr.matches("^([0-9a-fA-F]{4," + RevId.LEN + "})$");

    // By newer style changeKey?
    //
    boolean changeKeyParses = idstr.matches("^I[0-9a-f]*$");
    if (changeKeyParses) {
      for (ChangeData cd : queryProvider.get().byKeyPrefix(idstr)) {
        matchChange(matched, cd.change());
      }
    }

    // By commit?
    //
    if (isCommit) {
      RevId id = new RevId(idstr);
      ResultSet<PatchSet> patches;
      if (id.isComplete()) {
        patches = db.patchSets().byRevision(id);
      } else {
        patches = db.patchSets().byRevisionRange(id, id.max());
      }

      for (PatchSet ps : patches) {
        matchChange(matched, ps.getId().getParentKey());
      }
    }

    // By older style changeId?
    //
    boolean changeIdParses = false;
    if (idstr.matches("^[1-9][0-9]*$")) {
      Change.Id id;
      try {
        id = Change.Id.parse(idstr);
        changeIdParses = true;
      } catch (IllegalArgumentException e) {
        id = null;
        changeIdParses = false;
      }

      if (changeIdParses) {
        matchChange(matched, id);
      }
    }

    if (!changeKeyParses && !isCommit && !changeIdParses) {
      throw error("\"" + idstr + "\" is not a valid change");
    }

    switch (matched.size()) {
      case 0:
        throw error("\"" + idstr + "\" no such change");

      case 1:
        return matched;

      default:
        throw error("\"" + idstr + "\" matches multiple changes");
    }
  }
 private static AccountPatchReview getExisting(ReviewDb db, FileResource resource)
     throws OrmException {
   AccountPatchReview.Key key =
       new AccountPatchReview.Key(resource.getPatchKey(), resource.getAccountId());
   return db.accountPatchReviews().get(key);
 }
 private void afterTest() throws Exception {
   db.close();
   sshSession.close();
   server.stop();
 }
Beispiel #27
0
  private void setNew(ChangeNotes notes, final ChangeMessage msg)
      throws NoSuchChangeException, IOException {
    Change c = notes.getChange();

    Change change = null;
    ChangeUpdate update = null;
    try {
      db.changes().beginTransaction(c.getId());
      try {
        change =
            db.changes()
                .atomicUpdate(
                    c.getId(),
                    new AtomicUpdate<Change>() {
                      @Override
                      public Change update(Change c) {
                        if (c.getStatus().isOpen()) {
                          c.setStatus(Change.Status.NEW);
                          ChangeUtil.updated(c);
                        }
                        return c;
                      }
                    });
        ChangeControl control = changeControl(change);

        // TODO(yyonas): atomic change is not propagated.
        update = updateFactory.create(control, c.getLastUpdatedOn());
        if (msg != null) {
          cmUtil.addChangeMessage(db, update, msg);
        }
        db.commit();
      } finally {
        db.rollback();
      }
    } catch (OrmException err) {
      logWarn("Cannot record merge failure message", err);
    }
    if (update != null) {
      update.commit();
    }
    indexer.index(db, change);

    PatchSetApproval submitter = null;
    try {
      submitter = approvalsUtil.getSubmitter(db, notes, notes.getChange().currentPatchSetId());
    } catch (Exception e) {
      logError("Cannot get submitter for change " + notes.getChangeId(), e);
    }
    if (submitter != null) {
      try {
        hooks.doMergeFailedHook(
            c,
            accountCache.get(submitter.getAccountId()).getAccount(),
            db.patchSets().get(c.currentPatchSetId()),
            msg.getMessage(),
            db);
      } catch (OrmException ex) {
        logError("Cannot run hook for merge failed " + c.getId(), ex);
      }
    }
  }