Add option to force resume project import
Normally changes that have the same last modified timestamp in the
source and target system are skipped on resume. This is good since it
makes the resume faster and it avoids unneeded "Resumed import of ..."
messages on the changes. However in some cases these changes should
not be skipped. E.g. approvals for an unknown label are ignored during
an import, if later this label is configured on the target server, the
skipped approvals will still not appear in the target system after
resume if the change is skipped due to not having been modified. In
this case the resume can now be done forcefully.
Change-Id: I6be084dbed00d5e530beaa3904eb687a5c5fb849
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ImportProject.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ImportProject.java
index 76fefdd..74b8eb0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ImportProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ImportProject.java
@@ -97,6 +97,7 @@
private final Project.NameKey targetProject;
private Project.NameKey srcProject;
private Project.NameKey parent;
+ private boolean force;
private Writer err;
@@ -146,9 +147,10 @@
}
}
- public Response<String> resume(String user, String pass, File importStatus)
- throws RestApiException, OrmException, IOException, ValidationException,
- GitAPIException, NoSuchChangeException, NoSuchAccountException {
+ public Response<String> resume(String user, String pass, boolean force,
+ File importStatus) throws RestApiException, OrmException, IOException,
+ ValidationException, GitAPIException, NoSuchChangeException,
+ NoSuchAccountException {
LockFile lockFile = lockForImport();
try {
ImportProjectInfo info = ImportJson.parse(importStatus);
@@ -160,6 +162,8 @@
input.name = info.name;
input.parent = info.parent;
+ this.force = force;
+
return apply(lockFile, input, info);
} finally {
lockFile.unlock();
@@ -189,7 +193,7 @@
gitFetchStep.fetch(input.user, input.pass, repo, pm);
configProjectStep.configure(targetProject, parent, pm);
replayChangesFactory.create(input.from, input.user, input.pass, repo,
- srcProject, targetProject, resume, pm).replay();
+ srcProject, targetProject, force, resume, pm).replay();
} finally {
repo.close();
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayChangesStep.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayChangesStep.java
index e32d1ec..bffae8c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayChangesStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayChangesStep.java
@@ -53,7 +53,8 @@
Repository repo,
@Assisted("srcProject") Project.NameKey srcProject,
@Assisted("targetProject") Project.NameKey targetProject,
- boolean resume,
+ @Assisted("force") boolean force,
+ @Assisted("resume") boolean resume,
ProgressMonitor pm);
}
@@ -72,6 +73,7 @@
private final Repository repo;
private final Project.NameKey srcProject;
private final Project.NameKey targetProject;
+ private final boolean force;
private final boolean resume;
private final ProgressMonitor pm;
@@ -93,7 +95,8 @@
@Assisted Repository repo,
@Assisted("srcProject") Project.NameKey srcProject,
@Assisted("targetProject") Project.NameKey targetProject,
- @Assisted boolean resume,
+ @Assisted("force") boolean force,
+ @Assisted("resume") boolean resume,
@Assisted ProgressMonitor pm) {
this.replayRevisionsFactory = replayRevisionsFactory;
this.replayInlineCommentsFactory = replayInlineCommentsFactory;
@@ -110,6 +113,7 @@
this.repo = repo;
this.srcProject = srcProject;
this.targetProject = targetProject;
+ this.force = force;
this.resume = resume;
this.pm = pm;
}
@@ -147,7 +151,7 @@
change = createChange(c);
} else {
resumeChange = true;
- if (change.getLastUpdatedOn().equals(c.updated)) {
+ if (!force && change.getLastUpdatedOn().equals(c.updated)) {
// change was not modified since last import
return;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectCommand.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectCommand.java
index 4aa3d05..5dfb115 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectCommand.java
@@ -35,6 +35,9 @@
usage = "password of remote user")
private String pass;
+ @Option(name = "--force", usage = "Whether the resume should be done forcefully.")
+ private boolean force;
+
@Option(name = "--quiet", usage = "suppress progress messages")
private boolean quiet;
@@ -58,6 +61,7 @@
ResumeProjectImport.Input input = new ResumeProjectImport.Input();
input.user = user;
input.pass = pass;
+ input.force = force;
resume.apply(rsrc, input);
} catch (RestApiException e) {
throw die(e.getMessage());
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectImport.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectImport.java
index 521be04..ad172d4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectImport.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectImport.java
@@ -50,6 +50,7 @@
public static class Input {
public String user;
public String pass;
+ public boolean force;
}
private final ImportProject.Factory importProjectFactory;
@@ -74,7 +75,8 @@
ImportProject importer = importProjectFactory.create(rsrc.getName());
importer.setErr(err);
- return importer.resume(input.user, input.pass, rsrc.getImportStatus());
+ return importer.resume(input.user, input.pass, input.force,
+ rsrc.getImportStatus());
}
public static class OnProjects implements
diff --git a/src/main/resources/Documentation/cmd-resume-project.md b/src/main/resources/Documentation/cmd-resume-project.md
index 8221c5f..f5c7ebd 100644
--- a/src/main/resources/Documentation/cmd-resume-project.md
+++ b/src/main/resources/Documentation/cmd-resume-project.md
@@ -11,6 +11,7 @@
ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ resume-project \
--user <USER> | -u <USER> \
--pass - | <PASS> \
+ [--force] \
[--quiet] \
<NAME>
```
@@ -38,6 +39,11 @@
`--user`
: User on remote system.
+`--force`
+: Whether the resume should be done forcefully. On resume with force
+ changes that have the same last modified timestamp in the source
+ and target system are resumed, otherwise they will be skipped.
+
`--quiet`
: Suppress progress messages.
diff --git a/src/main/resources/Documentation/rest-api-config.md b/src/main/resources/Documentation/rest-api-config.md
index 380e584..8b01205 100644
--- a/src/main/resources/Documentation/rest-api-config.md
+++ b/src/main/resources/Documentation/rest-api-config.md
@@ -272,6 +272,9 @@
* _user_: User on remote system.
* _pass_: Password of remote user.
+* _force_: Whether the resume should be done forcefully. On resume with
+force changes that have the same last modified timestamp in the source
+and target system are resumed, otherwise they will be skipped.
SEE ALSO
diff --git a/src/main/resources/static/resume-project-import.js b/src/main/resources/static/resume-project-import.js
index eaf752d..fdca63c 100644
--- a/src/main/resources/static/resume-project-import.js
+++ b/src/main/resources/static/resume-project-import.js
@@ -17,10 +17,11 @@
var u = c.textfield();
var p = c.textfield();
p.type = 'password';
+ var f = c.checkbox();
var b = c.button('Resume',
{onclick: function(){
c.call(
- {user: u.value, pass: p.value},
+ {user: u.value, pass: p.value, force: f.checked},
function(r) {
c.hide();
window.alert('Import for project "'
@@ -38,6 +39,8 @@
c.br(),
c.prependLabel('Password:', p),
c.br(),
+ c.label(f, 'Force Resume'),
+ c.br(),
c.br(),
b));
}