Use refName instead of objectId in the fetch REST Api When requesting a remote fetch, specify the ref-name to be fetched instead of the SHA1 of the ref. Fetching by SHA1 has two issues: - The remote Git server may disallow exposing the fetch by SHA1 - Fetching the SHA1 does not update the local ref Change-Id: I52fba1166b0d5df3a498af2702328cc7723b9a41
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchAction.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchAction.java index ce02d56..736fbf0 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchAction.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchAction.java
@@ -51,7 +51,7 @@ public static class Input { public String label; - public String objectId; + public String refName; public boolean async; } @@ -62,8 +62,8 @@ throw new BadRequestException("Source label cannot be null or empty"); } - if (Strings.isNullOrEmpty(input.objectId)) { - throw new BadRequestException("Ref-update objectId cannot be null or empty"); + if (Strings.isNullOrEmpty(input.refName)) { + throw new BadRequestException("Ref-update refname cannot be null or empty"); } if (input.async) { @@ -83,7 +83,7 @@ private Response<?> applySync(Project.NameKey project, Input input) throws InterruptedException, ExecutionException, RemoteConfigurationMissingException, TimeoutException { - command.fetch(project, input.label, input.objectId); + command.fetch(project, input.label, input.refName); return Response.created(input); } @@ -117,16 +117,16 @@ @Override public void run() { try { - command.fetch(project, input.label, input.objectId); + command.fetch(project, input.label, input.refName); } catch (InterruptedException | ExecutionException | RemoteConfigurationMissingException | TimeoutException e) { log.atSevere().withCause(e).log( - "Exception during the async fetch call for project {}, label {} and object id {}", + "Exception during the async fetch call for project {}, label {} and ref name {}", project.get(), input.label, - input.objectId); + input.refName); } } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommand.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommand.java index 749adc2..b3ab83d 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommand.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommand.java
@@ -45,7 +45,7 @@ this.sources = sources; } - public void fetch(Project.NameKey name, String label, String objectId) + public void fetch(Project.NameKey name, String label, String refName) throws InterruptedException, ExecutionException, RemoteConfigurationMissingException, TimeoutException { ReplicationState state = @@ -59,7 +59,7 @@ } try { - Future<?> future = source.get().schedule(name, objectId, state, true); + Future<?> future = source.get().schedule(name, refName, state, true); state.markAllFetchTasksScheduled(); future.get(source.get().getTimeout(), TimeUnit.SECONDS); } catch (ExecutionException
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionTest.java index 045b882..39c6717 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchActionTest.java
@@ -49,7 +49,7 @@ FetchAction fetchAction; String label = "instance-2-label"; String url = "file:///gerrit-host/instance-1/git/${name}.git"; - String objectId = "c90989ed7a8ab01f1bdd022872428f020b866358"; + String refName = "refs/heads/master"; String location = "http://gerrit-host/a/config/server/tasks/08d173e9"; int taskId = 1234; @@ -83,7 +83,7 @@ public void shouldReturnCreatedResponseCode() throws RestApiException { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = label; - inputParams.objectId = objectId; + inputParams.refName = refName; Response<?> response = fetchAction.apply(projectResource, inputParams); @@ -92,10 +92,10 @@ @SuppressWarnings("cast") @Test - public void shouldReturnSourceUrlAndObjectIdAsAResponseBody() throws Exception { + public void shouldReturnSourceUrlAndrefNameAsAResponseBody() throws Exception { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = label; - inputParams.objectId = objectId; + inputParams.refName = refName; Response<?> response = fetchAction.apply(projectResource, inputParams); @@ -105,7 +105,7 @@ @Test(expected = BadRequestException.class) public void shouldThrowBadRequestExceptionWhenMissingLabel() throws Exception { FetchAction.Input inputParams = new FetchAction.Input(); - inputParams.objectId = objectId; + inputParams.refName = refName; fetchAction.apply(projectResource, inputParams); } @@ -114,13 +114,13 @@ public void shouldThrowBadRequestExceptionWhenEmptyLabel() throws Exception { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = ""; - inputParams.objectId = objectId; + inputParams.refName = refName; fetchAction.apply(projectResource, inputParams); } @Test(expected = BadRequestException.class) - public void shouldThrowBadRequestExceptionWhenMissingObjectId() throws Exception { + public void shouldThrowBadRequestExceptionWhenMissingrefName() throws Exception { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = label; @@ -128,10 +128,10 @@ } @Test(expected = BadRequestException.class) - public void shouldThrowBadRequestExceptionWhenEmptyObjectId() throws Exception { + public void shouldThrowBadRequestExceptionWhenEmptyrefName() throws Exception { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = label; - inputParams.objectId = ""; + inputParams.refName = ""; fetchAction.apply(projectResource, inputParams); } @@ -142,7 +142,7 @@ RemoteConfigurationMissingException, TimeoutException { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = label; - inputParams.objectId = objectId; + inputParams.refName = refName; doThrow(new InterruptedException()).when(fetchCommand).fetch(any(), any(), any()); @@ -155,7 +155,7 @@ RemoteConfigurationMissingException, TimeoutException { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = "non-existing-label"; - inputParams.objectId = objectId; + inputParams.refName = refName; doThrow(new RemoteConfigurationMissingException("")) .when(fetchCommand) @@ -170,7 +170,7 @@ RemoteConfigurationMissingException, TimeoutException { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = label; - inputParams.objectId = objectId; + inputParams.refName = refName; doThrow(new ExecutionException(new RuntimeException())) .when(fetchCommand) @@ -185,7 +185,7 @@ RemoteConfigurationMissingException, TimeoutException { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = label; - inputParams.objectId = objectId; + inputParams.refName = refName; doThrow(new IllegalStateException()).when(fetchCommand).fetch(any(), any(), any()); @@ -198,7 +198,7 @@ RemoteConfigurationMissingException, TimeoutException { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = label; - inputParams.objectId = objectId; + inputParams.refName = refName; doThrow(new TimeoutException()).when(fetchCommand).fetch(any(), any(), any()); @@ -209,7 +209,7 @@ public void shouldReturnScheduledTaskForAsyncCall() throws RestApiException { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = label; - inputParams.objectId = objectId; + inputParams.refName = refName; inputParams.async = true; Response<?> response = fetchAction.apply(projectResource, inputParams); @@ -220,7 +220,7 @@ public void shouldLocationHeaderForAsyncCall() throws Exception { FetchAction.Input inputParams = new FetchAction.Input(); inputParams.label = label; - inputParams.objectId = objectId; + inputParams.refName = refName; inputParams.async = true; Response<?> response = fetchAction.apply(projectResource, inputParams);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommandTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommandTest.java index 7536caf..e625e0f 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommandTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/api/FetchCommandTest.java
@@ -45,7 +45,7 @@ @RunWith(MockitoJUnitRunner.class) public class FetchCommandTest { - private static final String OBJECT_ID_TO_FETCH = "8f22c45da5ce298291b7329552568aae1bb62c10"; + private static final String REF_NAME_TO_FETCH = "refs/heads/master"; @Mock ReplicationState state; @Mock ReplicationState.Factory fetchReplicationStateFactory; @Mock PullReplicationStateLogger fetchStateLog; @@ -71,27 +71,27 @@ when(fetchReplicationStateFactory.create(any())).thenReturn(state); when(source.getRemoteConfigName()).thenReturn(label); when(sources.getAll()).thenReturn(Lists.newArrayList(source)); - when(source.schedule(projectName, OBJECT_ID_TO_FETCH, state, true)) + when(source.schedule(projectName, REF_NAME_TO_FETCH, state, true)) .thenReturn(CompletableFuture.completedFuture(null)); objectUnderTest = new FetchCommand(fetchReplicationStateFactory, fetchStateLog, sources); } @Test - public void shouldFetchRefUpdate() + public void shouldScheduleRefFetch() throws InterruptedException, ExecutionException, RemoteConfigurationMissingException, TimeoutException { - objectUnderTest.fetch(projectName, label, OBJECT_ID_TO_FETCH); + objectUnderTest.fetch(projectName, label, REF_NAME_TO_FETCH); - verify(source, times(1)).schedule(projectName, OBJECT_ID_TO_FETCH, state, true); + verify(source, times(1)).schedule(projectName, REF_NAME_TO_FETCH, state, true); } @Test public void shouldMarkAllFetchTasksScheduled() throws InterruptedException, ExecutionException, RemoteConfigurationMissingException, TimeoutException { - objectUnderTest.fetch(projectName, label, OBJECT_ID_TO_FETCH); + objectUnderTest.fetch(projectName, label, REF_NAME_TO_FETCH); - verify(source, times(1)).schedule(projectName, OBJECT_ID_TO_FETCH, state, true); + verify(source, times(1)).schedule(projectName, REF_NAME_TO_FETCH, state, true); verify(state, times(1)).markAllFetchTasksScheduled(); } @@ -99,7 +99,7 @@ public void shouldUpdateStateWhenRemoteConfigNameIsMissing() { assertThrows( RemoteConfigurationMissingException.class, - () -> objectUnderTest.fetch(projectName, "unknownLabel", OBJECT_ID_TO_FETCH)); + () -> objectUnderTest.fetch(projectName, "unknownLabel", REF_NAME_TO_FETCH)); verify(fetchStateLog, times(1)).error(anyString(), eq(state)); } @@ -108,12 +108,12 @@ public void shouldUpdateStateWhenInterruptedException() throws InterruptedException, ExecutionException, TimeoutException { when(future.get(anyLong(), eq(TimeUnit.SECONDS))).thenThrow(new InterruptedException()); - when(source.schedule(projectName, OBJECT_ID_TO_FETCH, state, true)).thenReturn(future); + when(source.schedule(projectName, REF_NAME_TO_FETCH, state, true)).thenReturn(future); InterruptedException e = assertThrows( InterruptedException.class, - () -> objectUnderTest.fetch(projectName, label, OBJECT_ID_TO_FETCH)); + () -> objectUnderTest.fetch(projectName, label, REF_NAME_TO_FETCH)); verify(fetchStateLog, times(1)).error(anyString(), eq(e), eq(state)); } @@ -123,12 +123,12 @@ throws InterruptedException, ExecutionException, TimeoutException { when(future.get(anyLong(), eq(TimeUnit.SECONDS))) .thenThrow(new ExecutionException(new Exception())); - when(source.schedule(projectName, OBJECT_ID_TO_FETCH, state, true)).thenReturn(future); + when(source.schedule(projectName, REF_NAME_TO_FETCH, state, true)).thenReturn(future); ExecutionException e = assertThrows( ExecutionException.class, - () -> objectUnderTest.fetch(projectName, label, OBJECT_ID_TO_FETCH)); + () -> objectUnderTest.fetch(projectName, label, REF_NAME_TO_FETCH)); verify(fetchStateLog, times(1)).error(anyString(), eq(e), eq(state)); } @@ -137,12 +137,12 @@ public void shouldUpdateStateWhenTimeoutException() throws InterruptedException, ExecutionException, TimeoutException { when(future.get(anyLong(), eq(TimeUnit.SECONDS))).thenThrow(new TimeoutException()); - when(source.schedule(projectName, OBJECT_ID_TO_FETCH, state, true)).thenReturn(future); + when(source.schedule(projectName, REF_NAME_TO_FETCH, state, true)).thenReturn(future); TimeoutException e = assertThrows( TimeoutException.class, - () -> objectUnderTest.fetch(projectName, label, OBJECT_ID_TO_FETCH)); + () -> objectUnderTest.fetch(projectName, label, REF_NAME_TO_FETCH)); verify(fetchStateLog, times(1)).error(anyString(), eq(e), eq(state)); } }