@Override public void serialize(Revision value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeNumber(value.major()); } }
/** * Returns {@code true} if the major value of {@code from} {@link Revision} or {@code to} {@link Revision} * is a negative integer. */ public boolean isRelative() { return from.isRelative() || to.isRelative(); }
/** * Returns {@code true} if the major value of {@code from} {@link Revision} is lower than the major * value of {@code to} {@link Revision}. * * @throws IllegalStateException if the {@code from} and {@code to} {@link Revision}s are in the * different state. They should be either absolute or relative. */ public boolean isAscending() { if (from.isRelative() != to.isRelative()) { throw new IllegalStateException("both of from: '" + from + "' and to: '" + to + "' should be absolute or relative."); } return from.compareTo(to) < 0; }
expected = Revision.INIT; } else { expected = headRevision.forward(1); checkState(revision.equals(expected), "incorrect revision: %s (expected: %s)", revision, expected); buf.putInt(revision.major()); commitId.copyRawTo(buf); buf.flip(); long pos = (long) (revision.major() - 1) * RECORD_LEN; try { do { headRevision.major() < revision.major()) { headRevision = revision;
creationTimeMillis(), author()); progressListener.accept(1, endRevision.major()); boolean success = false; try { for (int i = 2; i <= endRevision.major();) { new Revision(i), new Revision(Math.min(endRevision.major(), i + batch - 1)), Repository.ALL_PATH, batch); checkState(!commits.isEmpty(), "empty commits"); previousNonEmptyRevision = commits.get(0).revision().backward(1); checkState(revision.major() == i, "mismatching revision: %s (expected: %s)", revision.major(), i); final Revision baseRevision = revision.backward(1); final Collection<Change<?>> changes = blockingDiff(previousNonEmptyRevision, revision, Repository.ALL_PATH).values(); progressListener.accept(i, endRevision.major()); i++;
/** * GET /projects/{projectName}/repos/{repoName}/revision/{revision} * * <p>Normalizes the revision into an absolute revision. */ @Get("/projects/{projectName}/repos/{repoName}/revision/{revision}") @RequiresReadPermission public Map<String, Integer> normalizeRevision(Repository repository, @Param("revision") String revision) { final Revision normalizedRevision = repository.normalizeNow(new Revision(revision)); return ImmutableMap.of("revision", normalizedRevision.major()); } }
@Test public void testHistory_parameterCheck() throws Exception { // Make sure that we added at least one non-initial commit. repo.commit(HEAD, 0L, Author.UNKNOWN, SUMMARY, jsonUpserts[0]).join(); final Revision head = repo.normalizeNow(HEAD); List<Commit> commits; // Even though the range contains 1, if the path is specified and does not contain "/**", // it should not include the initial commit. commits = repo.history(HEAD, new Revision(1), "non_existing_path").join(); assertThat(commits).hasSize(0); // Should include the initial empty commit if the range contain 1 and the path contains "/**". commits = repo.history(HEAD, HEAD, "/**").join(); assertThat(commits).hasSize(1); // Should not include the initial empty commit if the range does not contain 1. commits = repo.history(HEAD, HEAD, "non_existing_path").join(); assertThat(commits).isEmpty(); assertThatThrownBy(() -> repo.history(head.forward(1), head.forward(2), "non_existing_path").join()) .isInstanceOf(CompletionException.class) .hasCauseInstanceOf(RevisionNotFoundException.class); assertThatThrownBy(() -> repo.history(head.forward(1), head.backward(1), "non_existing_path").join()) .isInstanceOf(CompletionException.class) .hasCauseInstanceOf(RevisionNotFoundException.class); assertThatThrownBy(() -> repo.history(null, HEAD, "non_existing_path").join()) .isInstanceOf(CompletionException.class) .hasCauseInstanceOf(NullPointerException.class); assertThatThrownBy(() -> repo.history(HEAD, null, "non_existing_path").join()) .isInstanceOf(CompletionException.class) .hasCauseInstanceOf(NullPointerException.class); }
private Revision blockingCommit( Revision baseRevision, long commitTimeMillis, Author author, String summary, String detail, Markup markup, Iterable<Change<?>> changes, boolean allowEmptyCommit) { requireNonNull(baseRevision, "baseRevision"); final CommitResult res; rwLock.writeLock().lock(); try { if (closePending.get() != null) { throw closePending.get().get(); } final Revision normBaseRevision = normalizeNow(baseRevision); final Revision headRevision = cachedHeadRevision(); if (headRevision.major() != normBaseRevision.major()) { throw new ChangeConflictException( "invalid baseRevision: " + baseRevision + " (expected: " + headRevision + " or equivalent)"); } res = commit0(headRevision, headRevision.forward(1), commitTimeMillis, author, summary, detail, markup, changes, allowEmptyCommit); this.headRevision = res.revision; } finally { rwLock.writeLock().unlock(); } // Note that the notification is made while no lock is held to avoid the risk of a dead lock. notifyWatchers(res.revision, res.parentTreeId, res.treeId); return res.revision; }
/** * Creates a new instance. */ public EntryNotFoundException(Revision revision, String path) { this(path + " (" + revision.text() + ')'); }
@Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof PushResult)) { return false; } final PushResult that = (PushResult) o; return revision.equals(that.revision) && when == that.when; }
void notify(Revision revision, String path) { List<Watch> eligibleWatches = null; synchronized (watchesMap) { for (final Entry<PathPatternFilter, Set<Watch>> e : watchesMap.entrySet()) { if (!e.getKey().matches(path)) { continue; } final Set<Watch> watches = e.getValue(); for (final Iterator<Watch> i = watches.iterator(); i.hasNext();) { final Watch w = i.next(); final Revision lastKnownRevision = w.lastKnownRevision; if (lastKnownRevision.compareTo(revision) < 0) { eligibleWatches = move(eligibleWatches, i, w); } else { logIneligibleFuture(lastKnownRevision, revision); } } } } if (eligibleWatches == null) { return; } // Notify the matching promises found above. final int numEligiblePromises = eligibleWatches.size(); for (int i = 0; i < numEligiblePromises; i++) { eligibleWatches.get(i).future.complete(revision); } }
@Test public void testWatchWithPathPattern() throws Exception { final Revision rev1 = repo.normalizeNow(HEAD); final Revision rev2 = rev1.forward(1); final Revision rev3 = rev2.forward(1); final CompletableFuture<Revision> f = repo.watch(rev1, jsonPaths[1]); // Should not notify when the path pattern does not match. repo.commit(rev1, 0L, Author.UNKNOWN, SUMMARY, jsonUpserts[0]).join(); assertThat(repo.normalizeNow(HEAD)).isEqualTo(rev2); assertThatThrownBy(() -> f.get(500, TimeUnit.MILLISECONDS)) .isInstanceOf(TimeoutException.class); // Should notify when the path pattern matches. repo.commit(rev2, 0L, Author.UNKNOWN, SUMMARY, jsonUpserts[1]).join(); assertThat(repo.normalizeNow(HEAD)).isEqualTo(rev3); assertThat(f.get(3, TimeUnit.SECONDS)).isEqualTo(rev3); }
/** * Run a sequence of add operation on the same path, valid the diff after each push. */ @Test public void testDiff_add() throws Exception { final String jsonPath = jsonUpserts[0].path(); final String textPath = textUpserts[0].path(); Revision prevRevison = repo.commit(HEAD, 0L, Author.UNKNOWN, SUMMARY, jsonUpserts[0], textUpserts[0]).join(); for (int i = 1; i < NUM_ITERATIONS; i++) { final Revision currRevision = repo.commit(HEAD, 0L, Author.UNKNOWN, SUMMARY, jsonPatches[i], textPatches[i]).join(); final Map<String, Change<?>> diff = repo.diff(prevRevison, currRevision, Repository.ALL_PATH).join(); assertThat(diff).hasSize(2) .containsEntry(jsonPath, jsonPatches[i]) .containsEntry(textPath, textPatches[i]); final Map<String, Change<?>> diff2 = repo.diff(HEAD.backward(1), HEAD, Repository.ALL_PATH).join(); assertThat(diff2).isEqualTo(diff); prevRevison = currRevision; } }
creationTimeMillis(), author()); progressListener.accept(1, endRevision.major()); boolean success = false; try { for (int i = 2; i <= endRevision.major();) { new Revision(i), new Revision(Math.min(endRevision.major(), i + batch - 1)), Repository.ALL_PATH, batch); checkState(!commits.isEmpty(), "empty commits"); previousNonEmptyRevision = commits.get(0).revision().backward(1); checkState(revision.major() == i, "mismatching revision: %s (expected: %s)", revision.major(), i); final Revision baseRevision = revision.backward(1); final Collection<Change<?>> changes = blockingDiff(previousNonEmptyRevision, revision, Repository.ALL_PATH).values(); progressListener.accept(i, endRevision.major()); i++;
/** * GET /projects/{projectName}/repos/{repoName}/revision/{revision} * * <p>Normalizes the revision into an absolute revision. */ @Get("/projects/{projectName}/repos/{repoName}/revision/{revision}") @RequiresReadPermission public Map<String, Integer> normalizeRevision(Repository repository, @Param("revision") String revision) { final Revision normalizedRevision = repository.normalizeNow(new Revision(revision)); return ImmutableMap.of("revision", normalizedRevision.major()); } }
expected = Revision.INIT; } else { expected = headRevision.forward(1); checkState(revision.equals(expected), "incorrect revision: %s (expected: %s)", revision, expected); buf.putInt(revision.major()); commitId.copyRawTo(buf); buf.flip(); long pos = (long) (revision.major() - 1) * RECORD_LEN; try { do { headRevision.major() < revision.major()) { headRevision = revision;
private Revision blockingCommit( Revision baseRevision, long commitTimeMillis, Author author, String summary, String detail, Markup markup, Iterable<Change<?>> changes, boolean allowEmptyCommit) { requireNonNull(baseRevision, "baseRevision"); final CommitResult res; rwLock.writeLock().lock(); try { if (closePending.get() != null) { throw closePending.get().get(); } final Revision normBaseRevision = normalizeNow(baseRevision); final Revision headRevision = cachedHeadRevision(); if (headRevision.major() != normBaseRevision.major()) { throw new ChangeConflictException( "invalid baseRevision: " + baseRevision + " (expected: " + headRevision + " or equivalent)"); } res = commit0(headRevision, headRevision.forward(1), commitTimeMillis, author, summary, detail, markup, changes, allowEmptyCommit); this.headRevision = res.revision; } finally { rwLock.writeLock().unlock(); } // Note that the notification is made while no lock is held to avoid the risk of a dead lock. notifyWatchers(res.revision, res.parentTreeId, res.treeId); return res.revision; }