private void updateReferenceWithNameChange( Repository repository, String currentRefName, ObjectId currentObjectId, String newRefName, ObjectId targetObjectId, Timestamp timestamp) throws IOException { BatchRefUpdate batchRefUpdate = repository.getRefDatabase().newBatchUpdate(); batchRefUpdate.addCommand(new ReceiveCommand(ObjectId.zeroId(), targetObjectId, newRefName)); batchRefUpdate.addCommand( new ReceiveCommand(currentObjectId, ObjectId.zeroId(), currentRefName)); batchRefUpdate.setRefLogMessage("rebase edit", false); batchRefUpdate.setRefLogIdent(getRefLogIdent(timestamp)); try (RevWalk revWalk = new RevWalk(repository)) { batchRefUpdate.execute(revWalk, NullProgressMonitor.INSTANCE); } for (ReceiveCommand cmd : batchRefUpdate.getCommands()) { if (cmd.getResult() != ReceiveCommand.Result.OK) { throw new IOException("failed: " + cmd); } } }
public void unstarAll(Project.NameKey project, Change.Id changeId) throws OrmException { try (Repository repo = repoManager.openRepository(allUsers); RevWalk rw = new RevWalk(repo)) { BatchRefUpdate batchUpdate = repo.getRefDatabase().newBatchUpdate(); batchUpdate.setAllowNonFastForwards(true); batchUpdate.setRefLogIdent(serverIdent); batchUpdate.setRefLogMessage("Unstar change " + changeId.get(), true); for (Account.Id accountId : byChangeFromIndex(changeId).keySet()) { String refName = RefNames.refsStarredChanges(changeId, accountId); Ref ref = repo.getRefDatabase().getRef(refName); batchUpdate.addCommand(new ReceiveCommand(ref.getObjectId(), ObjectId.zeroId(), refName)); } batchUpdate.execute(rw, NullProgressMonitor.INSTANCE); for (ReceiveCommand command : batchUpdate.getCommands()) { if (command.getResult() != ReceiveCommand.Result.OK) { throw new IOException( String.format( "Unstar change %d failed, ref %s could not be deleted: %s", changeId.get(), command.getRefName(), command.getResult())); } } indexer.index(dbProvider.get(), project, changeId); } catch (IOException e) { throw new OrmException(String.format("Unstar change %d failed", changeId.get()), e); } }
private void executeNoteDbUpdate(RevWalk rw, ObjectInserter ins, BatchRefUpdate bru) throws IOException { if (bru.getCommands().isEmpty()) { logDebug("No commands, skipping flush and ref update"); return; } ins.flush(); bru.setAllowNonFastForwards(true); bru.execute(rw, NullProgressMonitor.INSTANCE); for (ReceiveCommand cmd : bru.getCommands()) { // TODO(dborowitz): LOCK_FAILURE for NoteDb primary should be retried. if (cmd.getResult() != ReceiveCommand.Result.OK) { throw new IOException("Update failed: " + bru); } } }
@Nullable public BatchRefUpdate execute(boolean dryrun) throws OrmException, IOException { // Check before even inspecting the list, as this is a programmer error. if (migration.failChangeWrites()) { throw new OrmException(CHANGES_READ_ONLY); } if (isEmpty()) { return null; } try (Timer1.Context timer = metrics.updateLatency.start(CHANGES)) { stage(); // ChangeUpdates must execute before ChangeDraftUpdates. // // ChangeUpdate will automatically delete draft comments for any published // comments, but the updates to the two repos don't happen atomically. // Thus if the change meta update succeeds and the All-Users update fails, // we may have stale draft comments. Doing it in this order allows stale // comments to be filtered out by ChangeNotes, reflecting the fact that // comments can only go from DRAFT to PUBLISHED, not vice versa. BatchRefUpdate result = execute(changeRepo, dryrun, pushCert); execute(allUsersRepo, dryrun, null); return result; } finally { close(); } }
public void fire(Project.NameKey project, BatchRefUpdate batchRefUpdate, Account updater) { if (!listeners.iterator().hasNext()) { return; } for (ReceiveCommand cmd : batchRefUpdate.getCommands()) { if (cmd.getResult() == ReceiveCommand.Result.OK) { fire( project, cmd.getRefName(), cmd.getOldId(), cmd.getNewId(), cmd.getType(), util.accountInfo(updater)); } } }
public void deleteAllDraftsFromAllUsers(Change.Id changeId) throws IOException { try (Repository repo = repoManager.openRepository(allUsers); RevWalk rw = new RevWalk(repo)) { BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate(); for (Ref ref : getDraftRefs(repo, changeId)) { bru.addCommand(new ReceiveCommand(ref.getObjectId(), ObjectId.zeroId(), ref.getName())); } bru.setRefLogMessage("Delete drafts from NoteDb", false); bru.execute(rw, NullProgressMonitor.INSTANCE); for (ReceiveCommand cmd : bru.getCommands()) { if (cmd.getResult() != ReceiveCommand.Result.OK) { throw new IOException( String.format( "Failed to delete draft comment ref %s at %s: %s (%s)", cmd.getRefName(), cmd.getOldId(), cmd.getResult(), cmd.getMessage())); } } } }
@SafeVarargs private static BatchRefUpdate newBatchRefUpdate(Consumer<ReceiveCommand>... resultSetters) { try (Repository repo = new InMemoryRepository(new DfsRepositoryDescription("repo"))) { BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate(); for (int i = 0; i < resultSetters.length; i++) { ReceiveCommand cmd = new ReceiveCommand( ObjectId.fromString(String.format("%039x1", i)), ObjectId.fromString(String.format("%039x2", i)), "refs/heads/branch" + i); bru.addCommand(cmd); resultSetters[i].accept(cmd); } return bru; } }
private void updateRef(String notesBranch) throws LockFailureException, IOException { if (baseCommit != null && oursCommit.getTree().equals(baseCommit.getTree())) { // If the trees are identical, there is no change in the notes. // Avoid saving this commit as it has no new information. return; } BatchRefUpdate bru = db.getRefDatabase().newBatchUpdate(); bru.addCommand( new ReceiveCommand(firstNonNull(baseCommit, ObjectId.zeroId()), oursCommit, notesBranch)); RefUpdateUtil.executeChecked(bru, revWalk); gitRefUpdated.fire(project, bru, null); }
/** @see User#create(Project.NameKey, IdentifiedUser, BatchRefUpdate) */ public MetaDataUpdate create(Project.NameKey name, BatchRefUpdate batch) throws RepositoryNotFoundException, IOException { Repository repo = mgr.openRepository(name); MetaDataUpdate md = factory.create(name, repo, batch); md.setCloseRepository(true); md.getCommitBuilder().setAuthor(serverIdent); md.getCommitBuilder().setCommitter(serverIdent); return md; }
@Inject public MetaDataUpdate( GitReferenceUpdated gitRefUpdated, @Assisted Project.NameKey projectName, @Assisted Repository repository, @Assisted @Nullable BatchRefUpdate batch) { this.gitRefUpdated = gitRefUpdated; this.projectName = projectName; this.repository = repository; this.batch = batch; this.commit = new CommitBuilder(); }
public LockFailureException(String message, BatchRefUpdate batchRefUpdate) { super(message); refs = batchRefUpdate .getCommands() .stream() .filter(c -> c.getResult() == ReceiveCommand.Result.LOCK_FAILURE) .map(ReceiveCommand::getRefName) .collect(toImmutableList()); }
/** * Check results of all commands in the update batch, reducing to a single exception if there was * a failure. * * <p>Throws {@link LockFailureException} if at least one command failed with {@code * LOCK_FAILURE}, and the entire transaction was aborted, i.e. any non-{@code LOCK_FAILURE} * results, if there were any, failed with "transaction aborted". * * <p>In particular, if the underlying ref database does not {@link * org.eclipse.jgit.lib.RefDatabase#performsAtomicTransactions() perform atomic transactions}, * then a combination of {@code LOCK_FAILURE} on one ref and {@code OK} or another result on other * refs will <em>not</em> throw {@code LockFailureException}. * * @param bru batch update; should already have been executed. * @throws LockFailureException if the transaction was aborted due to lock failure. * @throws IOException if any result was not {@code OK}. */ @VisibleForTesting static void checkResults(BatchRefUpdate bru) throws IOException { if (bru.getCommands().isEmpty()) { return; } int lockFailure = 0; int aborted = 0; int failure = 0; for (ReceiveCommand cmd : bru.getCommands()) { if (cmd.getResult() != ReceiveCommand.Result.OK) { failure++; } if (cmd.getResult() == ReceiveCommand.Result.LOCK_FAILURE) { lockFailure++; } else if (cmd.getResult() == ReceiveCommand.Result.REJECTED_OTHER_REASON && JGitText.get().transactionAborted.equals(cmd.getMessage())) { aborted++; } } if (lockFailure + aborted == bru.getCommands().size()) { throw new LockFailureException("Update aborted with one or more lock failures: " + bru, bru); } else if (failure > 0) { throw new IOException("Update failed: " + bru); } }
private BatchRefUpdate execute(OpenRepo or, boolean dryrun, @Nullable PushCertificate pushCert) throws IOException { if (or == null || or.cmds.isEmpty()) { return null; } if (!dryrun) { or.flush(); } else { // OpenRepo buffers objects separately; caller may assume that objects are available in the // inserter it previously passed via setChangeRepo. checkState(saveObjects, "cannot use dryrun with saveObjects = false"); or.flushToFinalInserter(); } BatchRefUpdate bru = or.repo.getRefDatabase().newBatchUpdate(); bru.setPushCertificate(pushCert); if (refLogMessage != null) { bru.setRefLogMessage(refLogMessage, false); } else { bru.setRefLogMessage(firstNonNull(guessRestApiHandler(), "Update NoteDb refs"), false); } bru.setRefLogIdent(refLogIdent != null ? refLogIdent : serverIdent.get()); bru.setAtomic(atomicRefUpdates); or.cmds.addTo(bru); bru.setAllowNonFastForwards(true); if (!dryrun) { RefUpdateUtil.executeChecked(bru, or.rw); } return bru; }
@Override protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException { ListMultimap<Account.Id, Change.Id> imports = MultimapBuilder.hashKeys().arrayListValues().build(); try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement(); ResultSet rs = stmt.executeQuery("SELECT account_id, change_id FROM starred_changes")) { while (rs.next()) { Account.Id accountId = new Account.Id(rs.getInt(1)); Change.Id changeId = new Change.Id(rs.getInt(2)); imports.put(accountId, changeId); } } if (imports.isEmpty()) { return; } try (Repository git = repoManager.openRepository(allUsersName); RevWalk rw = new RevWalk(git)) { BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate(); ObjectId id = StarredChangesUtil.writeLabels(git, StarredChangesUtil.DEFAULT_LABELS); for (Map.Entry<Account.Id, Change.Id> e : imports.entries()) { bru.addCommand( new ReceiveCommand( ObjectId.zeroId(), id, RefNames.refsStarredChanges(e.getValue(), e.getKey()))); } bru.execute(rw, new TextProgressMonitor()); } catch (IOException | IllegalLabelException ex) { throw new OrmException(ex); } }
private void allowSubmoduleSubscription(Branch.NameKey subbranch, Branch.NameKey superBranch) throws OrmException { try (Repository git = mgr.openRepository(subbranch.getParentKey()); RevWalk rw = new RevWalk(git)) { BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate(); try (MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, subbranch.getParentKey(), git, bru)) { md.getCommitBuilder().setAuthor(serverUser); md.getCommitBuilder().setCommitter(serverUser); md.setMessage("Added superproject subscription during upgrade"); ProjectConfig pc = ProjectConfig.read(md); SubscribeSection s = null; for (SubscribeSection s1 : pc.getSubscribeSections(subbranch)) { if (s1.getProject().equals(superBranch.getParentKey())) { s = s1; } } if (s == null) { s = new SubscribeSection(superBranch.getParentKey()); pc.addSubscribeSection(s); } RefSpec newRefSpec = new RefSpec(subbranch.get() + ":" + superBranch.get()); if (!s.getMatchingRefSpecs().contains(newRefSpec)) { // For the migration we use only exact RefSpecs, we're not trying to // generalize it. s.addMatchingRefSpec(newRefSpec); } pc.commit(md); } bru.execute(rw, NullProgressMonitor.INSTANCE); } catch (ConfigInvalidException | IOException e) { throw new OrmException(e); } }
private void initSequences(Repository git, BatchRefUpdate bru) throws IOException { if (notesMigration.readChangeSequence() && git.exactRef(REFS_SEQUENCES + Sequences.NAME_CHANGES) == null) { // Can't easily reuse the inserter from MetaDataUpdate, but this shouldn't slow down site // initialization unduly. try (ObjectInserter ins = git.newObjectInserter()) { bru.addCommand(RepoSequence.storeNew(ins, Sequences.NAME_CHANGES, firstChangeId)); ins.flush(); } } }
private void execute(Repository git, BatchRefUpdate bru) throws IOException { try (RevWalk rw = new RevWalk(git)) { bru.execute(rw, NullProgressMonitor.INSTANCE); } for (ReceiveCommand cmd : bru.getCommands()) { if (cmd.getResult() != ReceiveCommand.Result.OK) { throw new IOException("Failed to initialize " + allProjectsName + " refs:\n" + bru); } } }
@Test public void sharedBatchRefUpdate() throws Exception { MyMetaData d1 = load("refs/meta/1", 0); MyMetaData d2 = load("refs/meta/2", 0); BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate(); try (BatchMetaDataUpdate batch1 = d1.openUpdate(newMetaDataUpdate(bru)); BatchMetaDataUpdate batch2 = d2.openUpdate(newMetaDataUpdate(bru))) { d1.setIncrement(1); batch1.write(d1, newCommitBuilder()); d2.setIncrement(2000); batch2.write(d2, newCommitBuilder()); d1.setIncrement(3); batch1.write(d1, newCommitBuilder()); d2.setIncrement(4000); batch2.write(d2, newCommitBuilder()); batch1.commit(); batch2.commit(); } assertMyMetaData(d1.getRefName(), 0); assertMyMetaData(d2.getRefName(), 0); assertThat(bru.getCommands().stream().map(ReceiveCommand::getRefName)) .containsExactly("refs/meta/1", "refs/meta/2"); try (RevWalk rw = new RevWalk(repo)) { RefUpdateUtil.executeChecked(bru, rw); } assertMyMetaData(d1.getRefName(), 4, "Increment conf.value by 1", "Increment conf.value by 3"); assertMyMetaData( d2.getRefName(), 6000, "Increment conf.value by 2000", "Increment conf.value by 4000"); }
private MetaDataUpdate newMetaDataUpdate(@Nullable BatchRefUpdate bru) { MetaDataUpdate u = new MetaDataUpdate(GitReferenceUpdated.DISABLED, project, repo, bru); CommitBuilder cb = newCommitBuilder(); u.getCommitBuilder().setAuthor(cb.getAuthor()); u.getCommitBuilder().setCommitter(cb.getCommitter()); return u; }
@Override protected void executeCommands() { if (getRepository().getRefDatabase() instanceof RefTreeDatabase) { List<ReceiveCommand> toApply = filterCommands(ReceiveCommand.Result.NOT_ATTEMPTED); if (toApply.isEmpty()) { return; } final BatchRefUpdate batch = ((RefTreeDatabase) getRepository().getRefDatabase()).getBootstrap().newBatchUpdate(); batch.setAllowNonFastForwards(true); batch.setAtomic(false); batch.setRefLogIdent(getRefLogIdent()); batch.setRefLogMessage("push", true); //$NON-NLS-1$ batch.addCommand(toApply); try { batch.setPushCertificate(getPushCertificate()); batch.execute(getRevWalk(), NullProgressMonitor.INSTANCE); } catch (IOException err) { for (ReceiveCommand cmd : toApply) { if (cmd.getResult() == ReceiveCommand.Result.NOT_ATTEMPTED) { cmd.setResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, MessageFormat.format( JGitText.get().lockError, err.getMessage())); } } } } else { super.executeCommands(); } }
MetaDataUpdate create( @Assisted Project.NameKey projectName, @Assisted Repository repository, @Assisted @Nullable BatchRefUpdate batch);
/** @return batch in which to run the update, or {@code null} for no batch. */ BatchRefUpdate getBatch() { return batch; }
@Nullable public BatchRefUpdate execute() throws OrmException, IOException { return execute(false); }
@Override public void fire(Project.NameKey project, BatchRefUpdate batchRefUpdate, Account updater) {}
@Override protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException { ListMultimap<Account.Id, AccountSshKey> imports = MultimapBuilder.hashKeys().arrayListValues().build(); try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement(); ResultSet rs = stmt.executeQuery( "SELECT " + "account_id, " + "seq, " + "ssh_public_key, " + "valid " + "FROM account_ssh_keys")) { while (rs.next()) { Account.Id accountId = new Account.Id(rs.getInt(1)); int seq = rs.getInt(2); String sshPublicKey = rs.getString(3); AccountSshKey key = new AccountSshKey(new AccountSshKey.Id(accountId, seq), sshPublicKey); boolean valid = toBoolean(rs.getString(4)); if (!valid) { key.setInvalid(); } imports.put(accountId, key); } } if (imports.isEmpty()) { return; } try (Repository git = repoManager.openRepository(allUsersName); RevWalk rw = new RevWalk(git)) { BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate(); for (Map.Entry<Account.Id, Collection<AccountSshKey>> e : imports.asMap().entrySet()) { try (MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git, bru)) { md.getCommitBuilder().setAuthor(serverUser); md.getCommitBuilder().setCommitter(serverUser); VersionedAuthorizedKeys authorizedKeys = new VersionedAuthorizedKeys(new SimpleSshKeyCreator(), e.getKey()); authorizedKeys.load(md); authorizedKeys.setKeys(fixInvalidSequenceNumbers(e.getValue())); authorizedKeys.commit(md); } } bru.execute(rw, NullProgressMonitor.INSTANCE); } catch (ConfigInvalidException | IOException ex) { throw new OrmException(ex); } }
@Override protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException { try (Repository git = repoManager.openRepository(allUsersName); RevWalk rw = new RevWalk(git)) { BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate(); bru.setAllowNonFastForwards(true); for (Ref ref : git.getRefDatabase().getRefs(RefNames.REFS_STARRED_CHANGES).values()) { StarRef starRef = StarredChangesUtil.readLabels(git, ref.getName()); Set<Integer> mutedPatchSets = StarredChangesUtil.getStarredPatchSets(starRef.labels(), MUTE_LABEL); if (mutedPatchSets.isEmpty()) { continue; } Set<Integer> reviewedPatchSets = StarredChangesUtil.getStarredPatchSets( starRef.labels(), StarredChangesUtil.REVIEWED_LABEL); Set<Integer> unreviewedPatchSets = StarredChangesUtil.getStarredPatchSets( starRef.labels(), StarredChangesUtil.UNREVIEWED_LABEL); List<String> newLabels = starRef .labels() .stream() .map( l -> { if (l.startsWith(MUTE_LABEL)) { Integer mutedPatchSet = Ints.tryParse(l.substring(MUTE_LABEL.length() + 1)); if (mutedPatchSet == null) { // unexpected format of mute label, must be a label that was manually // set, just leave it alone return l; } if (!reviewedPatchSets.contains(mutedPatchSet) && !unreviewedPatchSets.contains(mutedPatchSet)) { // convert mute label to reviewed label return StarredChangesUtil.REVIEWED_LABEL + "/" + mutedPatchSet; } // else patch set is muted but has either reviewed or unreviewed label // -> just drop the mute label return null; } return l; }) .filter(Objects::nonNull) .collect(toList()); ObjectId id = StarredChangesUtil.writeLabels(git, newLabels); bru.addCommand(new ReceiveCommand(ref.getTarget().getObjectId(), id, ref.getName())); } bru.execute(rw, new TextProgressMonitor()); } catch (IOException | IllegalLabelException ex) { throw new OrmException(ex); } }
private void initAllProjects(Repository git) throws IOException, ConfigInvalidException { BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate(); try (MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjectsName, git, bru)) { md.getCommitBuilder().setAuthor(serverUser); md.getCommitBuilder().setCommitter(serverUser); md.setMessage( MoreObjects.firstNonNull( Strings.emptyToNull(message), "Initialized Gerrit Code Review " + Version.getVersion())); ProjectConfig config = ProjectConfig.read(md); Project p = config.getProject(); p.setDescription("Access inherited by all other projects."); p.setRequireChangeID(InheritableBoolean.TRUE); p.setUseContentMerge(InheritableBoolean.TRUE); p.setUseContributorAgreements(InheritableBoolean.FALSE); p.setUseSignedOffBy(InheritableBoolean.FALSE); p.setEnableSignedPush(InheritableBoolean.FALSE); AccessSection cap = config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES, true); AccessSection all = config.getAccessSection(AccessSection.ALL, true); AccessSection heads = config.getAccessSection(AccessSection.HEADS, true); AccessSection tags = config.getAccessSection("refs/tags/*", true); AccessSection meta = config.getAccessSection(RefNames.REFS_CONFIG, true); AccessSection refsFor = config.getAccessSection("refs/for/*", true); AccessSection magic = config.getAccessSection("refs/for/" + AccessSection.ALL, true); grant(config, cap, GlobalCapability.ADMINISTRATE_SERVER, admin); grant(config, all, Permission.READ, admin, anonymous); grant(config, refsFor, Permission.ADD_PATCH_SET, registered); if (batch != null) { Permission priority = cap.getPermission(GlobalCapability.PRIORITY, true); PermissionRule r = rule(config, batch); r.setAction(Action.BATCH); priority.add(r); Permission stream = cap.getPermission(GlobalCapability.STREAM_EVENTS, true); stream.add(rule(config, batch)); } LabelType cr = initCodeReviewLabel(config); grant(config, heads, cr, -1, 1, registered); grant(config, heads, cr, -2, 2, admin, owners); grant(config, heads, Permission.CREATE, admin, owners); grant(config, heads, Permission.PUSH, admin, owners); grant(config, heads, Permission.SUBMIT, admin, owners); grant(config, heads, Permission.FORGE_AUTHOR, registered); grant(config, heads, Permission.FORGE_COMMITTER, admin, owners); grant(config, heads, Permission.EDIT_TOPIC_NAME, true, admin, owners); grant(config, tags, Permission.CREATE, admin, owners); grant(config, tags, Permission.CREATE_TAG, admin, owners); grant(config, tags, Permission.CREATE_SIGNED_TAG, admin, owners); grant(config, magic, Permission.PUSH, registered); grant(config, magic, Permission.PUSH_MERGE, registered); meta.getPermission(Permission.READ, true).setExclusiveGroup(true); grant(config, meta, Permission.READ, admin, owners); grant(config, meta, cr, -2, 2, admin, owners); grant(config, meta, Permission.CREATE, admin, owners); grant(config, meta, Permission.PUSH, admin, owners); grant(config, meta, Permission.SUBMIT, admin, owners); config.commitToNewRef(md, RefNames.REFS_CONFIG); initSequences(git, bru); execute(git, bru); } }
/** * Create an update using an existing batch ref update. * * <p>This allows batching together updates to multiple metadata refs. For making multiple * commits to a single metadata ref, see {@link VersionedMetaData#openUpdate(MetaDataUpdate)}. * * @param name project name. * @param user user for the update. * @param batch batch update to use; the caller is responsible for committing the update. */ public MetaDataUpdate create(Project.NameKey name, IdentifiedUser user, BatchRefUpdate batch) throws RepositoryNotFoundException, IOException { Repository repo = mgr.openRepository(name); MetaDataUpdate md = create(name, repo, user, batch); md.setCloseRepository(true); return md; }
/** * Create an update using an existing batch ref update. * * <p>This allows batching together updates to multiple metadata refs. For making multiple * commits to a single metadata ref, see {@link VersionedMetaData#openUpdate(MetaDataUpdate)}. * * <p>Important: Create a new MetaDataUpdate instance for each update: * * <pre> * <code> * try (Repository repo = repoMgr.openRepository(allUsersName); * RevWalk rw = new RevWalk(repo)) { * BatchRefUpdate batchUpdate = repo.getRefDatabase().newBatchUpdate(); * // WRONG: create the MetaDataUpdate instance here and reuse it for * // all updates in the loop * for{@code (Map.Entry<Account.Id, DiffPreferencesInfo> e : diffPrefsFromDb)} { * // CORRECT: create a new MetaDataUpdate instance for each update * try (MetaDataUpdate md = * metaDataUpdateFactory.create(allUsersName, batchUpdate)) { * md.setMessage("Import diff preferences from reviewdb\n"); * VersionedAccountPreferences vPrefs = * VersionedAccountPreferences.forUser(e.getKey()); * storeSection(vPrefs.getConfig(), UserConfigSections.DIFF, null, * e.getValue(), DiffPreferencesInfo.defaults()); * vPrefs.commit(md); * } catch (ConfigInvalidException e) { * // TODO handle exception * } * } * batchUpdate.execute(rw, NullProgressMonitor.INSTANCE); * } * </code> * </pre> * * @param name project name. * @param repository the repository to update; the caller is responsible for closing the * repository. * @param user user for the update. * @param batch batch update to use; the caller is responsible for committing the update. */ public MetaDataUpdate create( Project.NameKey name, Repository repository, IdentifiedUser user, BatchRefUpdate batch) { MetaDataUpdate md = factory.create(name, repository, batch); md.getCommitBuilder().setCommitter(serverIdent); md.setAuthor(user); return md; }
/** * Execute a batch ref update, throwing a checked exception if not all updates succeeded. * * @param bru batch update; should already have been executed. * @throws LockFailureException if the transaction was aborted due to lock failure; see {@link * #checkResults(BatchRefUpdate)} for details. * @throws IOException if any result was not {@code OK}. */ public static void executeChecked(BatchRefUpdate bru, RevWalk rw) throws IOException { bru.execute(rw, NullProgressMonitor.INSTANCE); checkResults(bru); }
/** * Add commands from this instance to a native JGit batch update. * * <p>Exactly one command per ref will be added to the update. The old SHA-1 will be the old SHA-1 * of the first command added to this instance for that ref; the new SHA-1 will be the new SHA-1 * of the last command. * * @param bru batch update */ public void addTo(BatchRefUpdate bru) { for (ReceiveCommand cmd : commands.values()) { bru.addCommand(cmd); } }