Merge branch 'stable-2.11' * stable-2.11: Remove unused imports in Helper.java Rename getPathSetWebLink to getPatchSetWebLink Improve class naming of group inclusion cache loaders Fix NPE when indexing changed lines Fix LDAP authentication for the RFC2307 server type Lazily lookup LDAP group memberships Configurable ldap.fetchMemberOfEagerly to optimize LDAP login Improve LDAP login times, transfer 40x less data. Reduce number of LDAP queries when having multiple accountBases Fix LDAP connection pool configuration. Improve method and variable names related to group inclusion caches Honor ldap.connectTimeout also without connection pooling Add config options of LDAP 'connection pooling' Change-Id: I2498f1eaa5ecd0d44ce4140394002f70424ab2ff
diff --git a/.buckconfig b/.buckconfig index e4a19f1..e3d0ffc 100644 --- a/.buckconfig +++ b/.buckconfig
@@ -9,6 +9,7 @@ docs = //Documentation:searchfree firefox = //:firefox gerrit = //:gerrit + headless = //:headless release = //:release safari = //:safari soyc = //gerrit-gwtui:ui_soyc
diff --git a/.buckversion b/.buckversion index 05c1944..9c09744 100644 --- a/.buckversion +++ b/.buckversion
@@ -1 +1 @@ -e8190a34ff10bdb55729a8a50669805f833f6a85 +79d36de9f5284f6e833cca81867d6088a25685fb
diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1f149cf --- /dev/null +++ b/.editorconfig
@@ -0,0 +1,11 @@ +# http://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2
diff --git a/BUCK b/BUCK index 2cd3fa8..02ee883 100644 --- a/BUCK +++ b/BUCK
@@ -1,6 +1,7 @@ include_defs('//tools/build.defs') gerrit_war(name = 'gerrit') +gerrit_war(name = 'headless', ui = None) gerrit_war(name = 'chrome', ui = 'ui_chrome') gerrit_war(name = 'firefox', ui = 'ui_firefox') gerrit_war(name = 'safari', ui = 'ui_safari')
diff --git a/Documentation/cmd-index.txt b/Documentation/cmd-index.txt index 7c664ac..f3bff7d 100644 --- a/Documentation/cmd-index.txt +++ b/Documentation/cmd-index.txt
@@ -75,6 +75,9 @@ link:cmd-review.html[gerrit review]:: Verify, approve and/or submit a patch set from the command line. +link:cmd-set-head.html[gerrit set-head]:: + Change the HEAD reference of a project. + link:cmd-set-reviewers.html[gerrit set-reviewers]:: Add or remove reviewers on a change.
diff --git a/Documentation/cmd-set-head.txt b/Documentation/cmd-set-head.txt new file mode 100644 index 0000000..d74caaa --- /dev/null +++ b/Documentation/cmd-set-head.txt
@@ -0,0 +1,45 @@ += gerrit set-head + +== NAME +gerrit set-head - Change a project's HEAD. + +== SYNOPSIS +-- +'ssh' -p <port> <host> 'gerrit set-head' <NAME> + --new-head <REF> +-- + +== DESCRIPTION +Modifies a given project's HEAD reference. + +The command is argument-safe, that is, if no argument is given the +previous settings are kept intact. + +== ACCESS +Caller must be an owner of the given project. + +== SCRIPTING +This command is intended to be used in scripts. + +== OPTIONS +<NAME>:: + Required; name of the project to change the HEAD. If name ends + with `.git` the suffix will be automatically removed. + +--new-head:: + Required; name of the ref that should be set as new HEAD. The + 'refs/heads/' prefix can be omitted. + +== EXAMPLES +Change HEAD of project `example` to `stable-2.11` branch: + +==== + $ ssh -p 29418 review.example.com gerrit set-head example --new-head stable-2.11 +==== + +GERRIT +------ +Part of link:index.html[Gerrit Code Review] + +SEARCHBOX +---------
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index 205ef08..9268267 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt
@@ -844,6 +844,30 @@ + Default is "Submit patch set ${patchSet} into ${branch}". +[[change.submitWholeTopic]]change.submitWholeTopic:: ++ +Determines if the submit button submits the whole topic instead of +just the current change. ++ +Default is false. + +[[change.submitTopicLabel]]change.submitTopicLabel:: ++ +If `change.submitWholeTopic` is set and a change has a topic, +the label name for the submit button is given here instead of +the configuration `change.submitLabel`. ++ +Defaults to "Submit whole topic" + +[[change.submitTopicTooltip]]change.submitTopicTooltip:: ++ +If `change.submitWholeTopic` is configuerd to true and a change has a +topic, this configuration determines the tooltip for the submit button +instead of `change.submitTooltip`. The variable `${topicSize}` is available +for the number of changes to be submitted. ++ +Defaults to "Submit all ${topicSize} changes within the topic". + [[change.replyLabel]]change.replyLabel:: + Label name for the reply button. In the user interface an ellipsis (…) @@ -2624,6 +2648,13 @@ and SSH. If set to true Administrators can install new plugins remotely, or disable existing plugins. Defaults to false. +[[plugins.jsLoadTimeout]]plugins.jsLoadTimeout:: ++ +Set the timeout value for loading JavaScript plugins in Gerrit UI. +Values can be specified using standard time unit abbreviations ('ms', +'sec', 'min', etc.). ++ +Default is 5 seconds. Negative values will be converted to 0. [[receive]] === Section receive
diff --git a/Documentation/dev-buck.txt b/Documentation/dev-buck.txt index 6bd3905..c234651 100644 --- a/Documentation/dev-buck.txt +++ b/Documentation/dev-buck.txt
@@ -116,6 +116,20 @@ ---- +=== Headless Mode + +To build Gerrit in headless mode, i.e. without the GWT Web UI: + +---- + buck build headless +---- + +The output executable WAR will be placed in: + +---- + buck-out/gen/headless.war +---- + === Extension and Plugin API JAR Files To build the extension, plugin and GWT API JAR files:
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt index 8bfac13..ebc59f4 100644 --- a/Documentation/dev-plugins.txt +++ b/Documentation/dev-plugins.txt
@@ -36,7 +36,7 @@ ---- mvn archetype:generate -DarchetypeGroupId=com.google.gerrit \ -DarchetypeArtifactId=gerrit-plugin-archetype \ - -DarchetypeVersion=2.10 \ + -DarchetypeVersion=2.12-SNAPSHOT \ -DgroupId=com.googlesource.gerrit.plugins.testplugin \ -DartifactId=testplugin ---- @@ -1717,17 +1717,18 @@ [[data-directory]] == Data Directory -Plugins can request a data directory with a `@PluginData` File -dependency. A data directory will be created automatically by the -server in `$site_path/data/$plugin_name` and passed to the plugin. +Plugins can request a data directory with a `@PluginData` Path (or File, +deprecated) dependency. A data directory will be created automatically +by the server in `$site_path/data/$plugin_name` and passed to the +plugin. Plugins can use this to store any data they want. [source,java] ---- @Inject -MyType(@PluginData java.io.File myDir) { - new FileInputStream(new File(myDir, "my.config")); +MyType(@PluginData java.nio.file.Path myDir) { + this.in = Files.newInputStream(myDir.resolve("my.config")); } ----
diff --git a/ReleaseNotes/ReleaseNotes-2.12.txt b/ReleaseNotes/ReleaseNotes-2.12.txt new file mode 100644 index 0000000..dfdcd37 --- /dev/null +++ b/ReleaseNotes/ReleaseNotes-2.12.txt
@@ -0,0 +1,41 @@ +Release notes for Gerrit 2.12 +============================= + + +Gerrit 2.12 is now available: + +link:https://gerrit-releases.storage.googleapis.com/gerrit-2.12.war[ +https://gerrit-releases.storage.googleapis.com/gerrit-2.12.war] + +Important Notes +--------------- + + +*WARNING:* Upgrading to 2.12.x requires the server be first upgraded to 2.8 (or +2.9) and then to 2.12.x. If you are upgrading from 2.8.x or later, you may ignore +this warning and upgrade directly to 2.12.x. + +*WARNING:* When upgrading from version 2.8.4 or older with a site that uses +Bouncy Castle Crypto, new versions of the libraries will be downloaded. The old +libraries should be manually removed from site's `lib` folder to prevent the +startup failure described in +link:https://code.google.com/p/gerrit/issues/detail?id=3084[Issue 3084]. + + +Release Highlights +------------------ + +* TODO + + +New Features +------------ + +* TODO + + +Upgrades +-------- + +* Upgrade gson to 2.3.1 +
diff --git a/VERSION b/VERSION index b05afb0..83d3d2a 100644 --- a/VERSION +++ b/VERSION
@@ -2,4 +2,4 @@ # Used by :api_install and :api_deploy targets # when talking to the destination repository. # -GERRIT_VERSION = '2.11-SNAPSHOT' +GERRIT_VERSION = '2.12-SNAPSHOT'
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java index 8548b5c..8f4c2d4 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
@@ -43,7 +43,8 @@ import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; import org.eclipse.jgit.lib.Config; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; class InMemoryTestingDatabaseModule extends LifecycleModule { private final Config cfg; @@ -58,9 +59,10 @@ .annotatedWith(GerritServerConfig.class) .toInstance(cfg); - bind(File.class) + // TODO(dborowitz): Use jimfs. + bind(Path.class) .annotatedWith(SitePath.class) - .toInstance(new File("UNIT_TEST_GERRIT_SITE")); + .toInstance(Paths.get("UNIT_TEST_GERRIT_SITE")); bind(GitRepositoryManager.class) .toInstance(new InMemoryRepositoryManager());
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java index 8945a22..7dffd5d 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -22,6 +22,8 @@ import org.junit.Test; +import java.util.List; + public class AccountIT extends AbstractDaemonTest { @Test @@ -59,4 +61,21 @@ .unstarChange(triplet); assertThat(getChange(triplet).starred).isNull(); } + + @Test + public void suggestAccounts() throws Exception { + String adminUsername = "admin"; + List<AccountInfo> result = gApi.accounts() + .suggestAccounts().withQuery(adminUsername).get(); + assertThat(result.size()).is(1); + assertThat(result.get(0).username).isEqualTo(adminUsername); + + List<AccountInfo> resultShortcutApi = gApi.accounts() + .suggestAccounts(adminUsername).get(); + assertThat(resultShortcutApi.size()).is(result.size()); + + List<AccountInfo> emptyResult = gApi.accounts() + .suggestAccounts("unknown").get(); + assertThat(emptyResult).isEmpty(); + } }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java index 790d3c5..c7958cc 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
@@ -222,53 +222,37 @@ } private void assertCommit(Project.NameKey project, String branch) throws IOException { - Repository r = repoManager.openRepository(project); - try { - RevWalk rw = new RevWalk(r); - try { - RevCommit c = rw.parseCommit(r.getRef(branch).getObjectId()); - assertThat(c.getShortMessage()).isEqualTo(PushOneCommit.SUBJECT); - assertThat(c.getAuthorIdent().getEmailAddress()).isEqualTo(admin.email); - assertThat(c.getCommitterIdent().getEmailAddress()).isEqualTo( - admin.email); - } finally { - rw.release(); - } - } finally { - r.close(); + try (Repository r = repoManager.openRepository(project); + RevWalk rw = new RevWalk(r)) { + RevCommit c = rw.parseCommit(r.getRef(branch).getObjectId()); + assertThat(c.getShortMessage()).isEqualTo(PushOneCommit.SUBJECT); + assertThat(c.getAuthorIdent().getEmailAddress()).isEqualTo(admin.email); + assertThat(c.getCommitterIdent().getEmailAddress()).isEqualTo( + admin.email); } } private void assertMergeCommit(String branch, String subject) throws IOException { - Repository r = repoManager.openRepository(project); - try { - RevWalk rw = new RevWalk(r); - try { - RevCommit c = rw.parseCommit(r.getRef(branch).getObjectId()); - assertThat(c.getParentCount()).is(2); - assertThat(c.getShortMessage()).isEqualTo("Merge \"" + subject + "\""); - assertThat(c.getAuthorIdent().getEmailAddress()).isEqualTo(admin.email); - assertThat(c.getCommitterIdent().getEmailAddress()).isEqualTo( - serverIdent.getEmailAddress()); - } finally { - rw.release(); - } - } finally { - r.close(); + try (Repository r = repoManager.openRepository(project); + RevWalk rw = new RevWalk(r)) { + RevCommit c = rw.parseCommit(r.getRef(branch).getObjectId()); + assertThat(c.getParentCount()).is(2); + assertThat(c.getShortMessage()).isEqualTo("Merge \"" + subject + "\""); + assertThat(c.getAuthorIdent().getEmailAddress()).isEqualTo(admin.email); + assertThat(c.getCommitterIdent().getEmailAddress()).isEqualTo( + serverIdent.getEmailAddress()); } } private void assertTag(Project.NameKey project, String branch, PushOneCommit.Tag tag) throws IOException { - Repository repo = repoManager.openRepository(project); - try { + try (Repository repo = repoManager.openRepository(project)) { Ref tagRef = repo.getRef(tag.name); assertThat(tagRef).isNotNull(); ObjectId taggedCommit = null; if (tag instanceof PushOneCommit.AnnotatedTag) { PushOneCommit.AnnotatedTag annotatedTag = (PushOneCommit.AnnotatedTag)tag; - RevWalk rw = new RevWalk(repo); - try { + try (RevWalk rw = new RevWalk(repo)) { RevObject object = rw.parseAny(tagRef.getObjectId()); assertThat(object).isInstanceOf(RevTag.class); RevTag tagObject = (RevTag) object; @@ -276,8 +260,6 @@ .isEqualTo(annotatedTag.message); assertThat(tagObject.getTaggerIdent()).isEqualTo(annotatedTag.tagger); taggedCommit = tagObject.getObject(); - } finally { - rw.dispose(); } } else { taggedCommit = tagRef.getObjectId(); @@ -285,8 +267,6 @@ ObjectId headCommit = repo.getRef(branch).getObjectId(); assertThat(taggedCommit).isNotNull(); assertThat(taggedCommit).isEqualTo(headCommit); - } finally { - repo.close(); } }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java index 66911b8..216823a 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -22,6 +22,7 @@ import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_REVISION; import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.gerrit.acceptance.AbstractDaemonTest; @@ -35,6 +36,7 @@ import com.google.gerrit.extensions.api.changes.SubmitInput; import com.google.gerrit.extensions.client.ChangeStatus; import com.google.gerrit.extensions.client.InheritableBoolean; +import com.google.gerrit.extensions.client.ListChangesOption; import com.google.gerrit.extensions.client.SubmitType; import com.google.gerrit.extensions.common.ChangeInfo; import com.google.gerrit.extensions.common.LabelInfo; @@ -143,11 +145,31 @@ createChange(git, "Change 1", "a.txt", "content", "test-topic"); PushOneCommit.Result change2 = createChange(git, "Change 2", "b.txt", "content", "test-topic"); + PushOneCommit.Result change3 = + createChange(git, "Change 3", "c.txt", "content", "test-topic"); approve(change1.getChangeId()); approve(change2.getChangeId()); - submit(change2.getChangeId()); + approve(change3.getChangeId()); + submit(change3.getChangeId()); change1.assertChange(Change.Status.MERGED, "test-topic", admin); change2.assertChange(Change.Status.MERGED, "test-topic", admin); + change3.assertChange(Change.Status.MERGED, "test-topic", admin); + assertSubmitter(change1); + assertSubmitter(change2); + assertSubmitter(change3); + } + + private void assertSubmitter(PushOneCommit.Result change) throws Exception { + ChangeInfo info = get(change.getChangeId(), ListChangesOption.MESSAGES); + assertThat((Iterable<?>)info.messages).isNotNull(); + assertThat((Iterable<?>)info.messages).hasSize(3); + if (getSubmitType() == SubmitType.CHERRY_PICK) { + assertThat(Iterables.getLast(info.messages).message).startsWith( + "Change has been successfully cherry-picked as "); + } else { + assertThat(Iterables.getLast(info.messages).message).isEqualTo( + "Change has been successfully merged into the git repository by Administrator"); + } } protected Git createProject() throws JSchException, IOException, @@ -337,40 +359,23 @@ } protected RevCommit getRemoteHead() throws IOException { - Repository repo = repoManager.openRepository(project); - try { + try (Repository repo = repoManager.openRepository(project)) { return getHead(repo, "refs/heads/master"); - } finally { - repo.close(); } } protected List<RevCommit> getRemoteLog() throws IOException { - Repository repo = repoManager.openRepository(project); - try { - RevWalk rw = new RevWalk(repo); - try { - rw.markStart(rw.parseCommit( - repo.getRef("refs/heads/master").getObjectId())); - return Lists.newArrayList(rw); - } finally { - rw.release(); - } - } finally { - repo.close(); + try (Repository repo = repoManager.openRepository(project); + RevWalk rw = new RevWalk(repo)) { + rw.markStart(rw.parseCommit( + repo.getRef("refs/heads/master").getObjectId())); + return Lists.newArrayList(rw); } } private RevCommit getHead(Repository repo, String name) throws IOException { - try { - RevWalk rw = new RevWalk(repo); - try { - return rw.parseCommit(repo.getRef(name).getObjectId()); - } finally { - rw.release(); - } - } finally { - repo.close(); + try (RevWalk rw = new RevWalk(repo)) { + return rw.parseCommit(repo.getRef(name).getObjectId()); } } @@ -381,28 +386,22 @@ } private String getLatestRemoteDiff() throws IOException { - Repository repo = repoManager.openRepository(project); - try { - RevWalk rw = new RevWalk(repo); - try { - ObjectId oldTreeId = repo.resolve("refs/heads/master~1^{tree}"); - ObjectId newTreeId = repo.resolve("refs/heads/master^{tree}"); - return getLatestDiff(repo, oldTreeId, newTreeId); - } finally { - rw.release(); - } - } finally { - repo.close(); + try (Repository repo = repoManager.openRepository(project); + RevWalk rw = new RevWalk(repo)) { + ObjectId oldTreeId = repo.resolve("refs/heads/master~1^{tree}"); + ObjectId newTreeId = repo.resolve("refs/heads/master^{tree}"); + return getLatestDiff(repo, oldTreeId, newTreeId); } } private String getLatestDiff(Repository repo, ObjectId oldTreeId, ObjectId newTreeId) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); - DiffFormatter fmt = new DiffFormatter(out); - fmt.setRepository(repo); - fmt.format(oldTreeId, newTreeId); - fmt.flush(); - return out.toString(); + try (DiffFormatter fmt = new DiffFormatter(out)) { + fmt.setRepository(repo); + fmt.format(oldTreeId, newTreeId); + fmt.flush(); + return out.toString(); + } } }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java index afcd5d0..fac87b7 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java
@@ -53,15 +53,9 @@ approve(changeId); Map<String, ActionInfo> actions = getActions(changeId); commonActionsAssertions(actions); - if (isSubmitWholeTopicEnabled()) { - ActionInfo info = actions.get("submit"); - assertThat(info.enabled).isTrue(); - assertThat(info.label).isEqualTo("Submit whole topic"); - assertThat(info.method).isEqualTo("POST"); - assertThat(info.title).isEqualTo("Submit all 1 changes of the same topic"); - } else { - noSubmitWholeTopicAssertions(actions); - } + // We want to treat a single change in a topic not as a whole topic, + // so regardless of how submitWholeTopic is configured: + noSubmitWholeTopicAssertions(actions); } @Test
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java index 998c5ea..68c9a5e 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
@@ -238,11 +238,10 @@ private void assertEmptyCommit(String projectName, String... refs) throws RepositoryNotFoundException, IOException { - Repository repo = - repoManager.openRepository(new Project.NameKey(projectName)); - RevWalk rw = new RevWalk(repo); - TreeWalk tw = new TreeWalk(repo); - try { + Project.NameKey projectKey = new Project.NameKey(projectName); + try (Repository repo = repoManager.openRepository(projectKey); + RevWalk rw = new RevWalk(repo); + TreeWalk tw = new TreeWalk(rw.getObjectReader())) { for (String ref : refs) { RevCommit commit = rw.lookupCommit(repo.getRef(ref).getObjectId()); rw.parseBody(commit); @@ -250,9 +249,6 @@ assertThat(tw.next()).isFalse(); tw.reset(); } - } finally { - rw.release(); - repo.close(); } } }
diff --git a/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java b/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java index 5870f91..fcacf78 100644 --- a/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java +++ b/gerrit-cache-h2/src/main/java/com/google/gerrit/server/cache/h2/H2CacheFactory.java
@@ -37,7 +37,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; @@ -51,7 +53,7 @@ private final DefaultCacheFactory defaultFactory; private final Config config; - private final File cacheDir; + private final Path cacheDir; private final List<H2CacheImpl<?, ?>> caches; private final DynamicMap<Cache<?, ?>> cacheMap; private final ExecutorService executor; @@ -65,23 +67,7 @@ DynamicMap<Cache<?, ?>> cacheMap) { defaultFactory = defaultCacheFactory; config = cfg; - - File loc = site.resolve(cfg.getString("cache", null, "directory")); - if (loc == null) { - cacheDir = null; - } else if (loc.exists() || loc.mkdirs()) { - if (loc.canWrite()) { - log.info("Enabling disk cache " + loc.getAbsolutePath()); - cacheDir = loc; - } else { - log.warn("Can't write to disk cache: " + loc.getAbsolutePath()); - cacheDir = null; - } - } else { - log.warn("Can't create disk cache: " + loc.getAbsolutePath()); - cacheDir = null; - } - + cacheDir = getCacheDir(site, cfg.getString("cache", null, "directory")); caches = Lists.newLinkedList(); this.cacheMap = cacheMap; @@ -103,6 +89,27 @@ } } + private static Path getCacheDir(SitePaths site, String name) { + if (name == null) { + return null; + } + Path loc = site.resolve(name); + if (!Files.exists(loc)) { + try { + Files.createDirectories(loc); + } catch (IOException e) { + log.warn("Can't create disk cache: " + loc.toAbsolutePath()); + return null; + } + } + if (!Files.isWritable(loc)) { + log.warn("Can't write to disk cache: " + loc.toAbsolutePath()); + return null; + } + log.info("Enabling disk cache " + loc.toAbsolutePath()); + return loc; + } + @Override public void start() { if (executor != null) { @@ -213,8 +220,7 @@ TypeLiteral<K> keyType, long maxSize, Long expireAfterWrite) { - File db = new File(cacheDir, name).getAbsoluteFile(); - String url = "jdbc:h2:" + db.toURI().toString(); + String url = "jdbc:h2:" + cacheDir.resolve(name).toUri(); return new SqlStore<>(url, keyType, maxSize, expireAfterWrite == null ? 0 : expireAfterWrite.longValue()); }
diff --git a/gerrit-common/BUCK b/gerrit-common/BUCK index 88e503e..484136a 100644 --- a/gerrit-common/BUCK +++ b/gerrit-common/BUCK
@@ -51,6 +51,7 @@ '//lib:guava', '//lib/jgit:jgit', '//lib/joda:joda-time', + '//lib/log:api', ], visibility = ['PUBLIC'], )
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java b/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java index bed10d6..2335b8d1 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/FileUtil.java
@@ -21,6 +21,8 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; public class FileUtil { @@ -42,6 +44,11 @@ } } + public static void chmod(final int mode, final Path path) { + // TODO(dborowitz): Is there a portable way to do this with NIO? + chmod(mode, path.toFile()); + } + public static void chmod(final int mode, final File path) { path.setReadable(false, false /* all */); path.setWritable(false, false /* all */); @@ -61,6 +68,33 @@ } } + /** + * Get the last modified time of a path. + * <p> + * Equivalent to {@code File#lastModified()}, returning 0 on errors, including + * file not found. Callers that prefer exceptions can use {@link + * Files#getLastModifiedTime(Path, java.nio.file.LinkOption...)}. + * + * @param p path. + * @return last modified time, in milliseconds since epoch. + */ + public static long lastModified(Path p) { + try { + return Files.getLastModifiedTime(p).toMillis(); + } catch (IOException e) { + return 0; + } + } + + public static Path mkdirsOrDie(Path p, String errMsg) { + try { + Files.createDirectories(p); + return p; + } catch (IOException e) { + throw new Die(errMsg + ": " + p, e); + } + } + private FileUtil() { } -} \ No newline at end of file +}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java b/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java index c45d9f9..9a30696 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java
@@ -16,7 +16,6 @@ import com.google.common.collect.Sets; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -25,6 +24,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Path; import java.util.Arrays; import java.util.Set; @@ -53,7 +53,7 @@ }.start(); } - public static void loadJARs(File... jars) { + public static void loadJARs(Iterable<Path> jars) { ClassLoader cl = IoUtil.class.getClassLoader(); if (!(cl instanceof URLClassLoader)) { throw noAddURL("Not loaded by URLClassLoader", null); @@ -71,9 +71,9 @@ } Set<URL> have = Sets.newHashSet(Arrays.asList(urlClassLoader.getURLs())); - for (File path : jars) { + for (Path path : jars) { try { - URL url = path.toURI().toURL(); + URL url = path.toUri().toURL(); if (have.add(url)) { addURL.invoke(cl, url); } @@ -86,6 +86,10 @@ } } + public static void loadJARs(Path... jars) { + loadJARs(Arrays.asList(jars)); + } + private static UnsupportedOperationException noAddURL(String m, Throwable why) { String prefix = "Cannot extend classpath: "; return new UnsupportedOperationException(prefix + m, why);
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PluginData.java b/gerrit-common/src/main/java/com/google/gerrit/common/PluginData.java index ffdae9d..27dc639 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/PluginData.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/PluginData.java
@@ -14,18 +14,18 @@ package com.google.gerrit.common; -import java.io.File; +import java.nio.file.Path; import java.util.Objects; public class PluginData { public final String name; public final String version; - public final File pluginFile; + public final Path pluginPath; - public PluginData(String name, String version, File pluginFile) { + public PluginData(String name, String version, Path pluginPath) { this.name = name; this.version = version; - this.pluginFile = pluginFile; + this.pluginPath = pluginPath; } @Override @@ -33,13 +33,13 @@ if (obj instanceof PluginData) { PluginData o = (PluginData) obj; return Objects.equals(name, o.name) && Objects.equals(version, o.version) - && Objects.equals(pluginFile, o.pluginFile); + && Objects.equals(pluginPath, o.pluginPath); } return super.equals(obj); } @Override public int hashCode() { - return Objects.hash(name, version, pluginFile); + return Objects.hash(name, version, pluginPath); } -} \ No newline at end of file +}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/SiteLibraryLoaderUtil.java b/gerrit-common/src/main/java/com/google/gerrit/common/SiteLibraryLoaderUtil.java index a98e0a5..2511a51 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/SiteLibraryLoaderUtil.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/SiteLibraryLoaderUtil.java
@@ -14,41 +14,57 @@ package com.google.gerrit.common; -import java.io.File; -import java.io.FileFilter; -import java.util.Arrays; -import java.util.Comparator; +import static com.google.gerrit.common.FileUtil.lastModified; + +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Ordering; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.util.List; public final class SiteLibraryLoaderUtil { + private static final Logger log = + LoggerFactory.getLogger(SiteLibraryLoaderUtil.class); - public static void loadSiteLib(File libdir) { - File[] jars = listJars(libdir); - if (jars != null && 0 < jars.length) { - Arrays.sort(jars, new Comparator<File>() { - @Override - public int compare(File a, File b) { - // Sort by reverse last-modified time so newer JARs are first. - int cmp = Long.compare(b.lastModified(), a.lastModified()); - if (cmp != 0) { - return cmp; - } - return a.getName().compareTo(b.getName()); - } - }); - IoUtil.loadJARs(jars); + public static void loadSiteLib(Path libdir) { + try { + IoUtil.loadJARs(listJars(libdir)); + } catch (IOException e) { + log.error("Error scanning lib directory " + libdir, e); } } - public static File[] listJars(File libdir) { - File[] jars = libdir.listFiles(new FileFilter() { + public static List<Path> listJars(Path dir) throws IOException { + DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() { @Override - public boolean accept(File path) { - String name = path.getName(); - return (name.endsWith(".jar") || name.endsWith(".zip")) - && path.isFile(); + public boolean accept(Path entry) throws IOException { + String name = entry.getFileName().toString(); + return (name.endsWith(".jar") || name.endsWith(".zip")) + && Files.isRegularFile(entry); } - }); - return jars; + }; + try (DirectoryStream<Path> jars = Files.newDirectoryStream(dir, filter)) { + return new Ordering<Path>() { + @Override + public int compare(Path a, Path b) { + // Sort by reverse last-modified time so newer JARs are first. + return ComparisonChain.start() + .compare(lastModified(b), lastModified(a)) + .compare(a, b) + .result(); + } + }.sortedCopy(jars); + } catch (NoSuchFileException nsfe) { + return ImmutableList.of(); + } } private SiteLibraryLoaderUtil() {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java index 430c23c..fa3d7a8 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
@@ -30,6 +30,7 @@ public Theme theme; public List<String> plugins; public List<Message> messages; + public Integer pluginsLoadTimeout; public boolean isNoteDbEnabled; public static class Theme {
diff --git a/gerrit-extension-api/pom.xml b/gerrit-extension-api/pom.xml index a0d9455..d0204e4 100644 --- a/gerrit-extension-api/pom.xml +++ b/gerrit-extension-api/pom.xml
@@ -2,7 +2,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-extension-api</artifactId> - <version>2.11-SNAPSHOT</version> + <version>2.12-SNAPSHOT</version> <packaging>jar</packaging> <name>Gerrit Code Review - Extension API</name> <description>API for Gerrit Extensions</description>
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginData.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginData.java index 75238a8..4893beff 100644 --- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginData.java +++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginData.java
@@ -18,24 +18,25 @@ import com.google.inject.BindingAnnotation; -import java.lang.annotation.ElementType; import java.lang.annotation.Retention; -import java.lang.annotation.Target; /** * Local path where a plugin can store its own private data. * <p> * A plugin or extension may receive this string by Guice injection to discover * a directory where it can store configuration or other data that is private: + * <p> + * This binding is on both {@link java.io.File} and {@link java.nio.file.Path}, + * pointing to the same location. The {@code File} version should be considered + * deprecated and may be removed in a future version. * * <pre> * {@literal @Inject} - * MyType(@PluginData java.io.File myDir) { - * new FileInputStream(new File(myDir, "my.config")); + * MyType(@PluginData java.nio.file.Path myDir) { + * this.in = Files.newInputStream(myDir.resolve("my.config")); * } * </pre> */ -@Target({ElementType.PARAMETER, ElementType.FIELD}) @Retention(RUNTIME) @BindingAnnotation public @interface PluginData {
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java index 71a93d3..32f8488 100644 --- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java +++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java
@@ -14,9 +14,12 @@ package com.google.gerrit.extensions.api.accounts; +import com.google.gerrit.extensions.common.AccountInfo; import com.google.gerrit.extensions.restapi.NotImplementedException; import com.google.gerrit.extensions.restapi.RestApiException; +import java.util.List; + public interface Accounts { /** * Look up an account by ID. @@ -42,6 +45,69 @@ AccountApi self() throws RestApiException; /** + * Suggest users for a given query. + * <p> + * Example code: + * {@code suggestAccounts().withQuery("Reviewer").withLimit(5).get()} + * + * @return API for setting parameters and getting result. + */ + SuggestAccountsRequest suggestAccounts() throws RestApiException; + + /** + * Suggest users for a given query. + * <p> + * Shortcut API for {@code suggestAccounts().withQuery(String)}. + * + * @see #suggestAccounts() + */ + SuggestAccountsRequest suggestAccounts(String query) + throws RestApiException; + + /** + * API for setting parameters and getting result. + * Used for {@code suggestAccounts()}. + * + * @see #suggestAccounts() + */ + public abstract class SuggestAccountsRequest { + private String query; + private int limit; + + /** + * Executes query and returns a list of accounts. + */ + public abstract List<AccountInfo> get() throws RestApiException; + + /** + * Set query. + * + * @param query needs to be in human-readable form. + */ + public SuggestAccountsRequest withQuery(String query) { + this.query = query; + return this; + } + + /** + * Set limit for returned list of accounts. + * Optional; server-default is used when not provided. + */ + public SuggestAccountsRequest withLimit(int limit) { + this.limit = limit; + return this; + } + + public String getQuery() { + return query; + } + + public int getLimit() { + return limit; + } + } + + /** * A default implementation which allows source compatibility * when adding new methods to the interface. **/ @@ -55,5 +121,16 @@ public AccountApi self() throws RestApiException { throw new NotImplementedException(); } + + @Override + public SuggestAccountsRequest suggestAccounts() throws RestApiException { + throw new NotImplementedException(); + } + + @Override + public SuggestAccountsRequest suggestAccounts(String query) + throws RestApiException { + throw new NotImplementedException(); + } } }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java index 718b36f..bd0fc41 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -579,6 +579,7 @@ AccountApi.self().view("preferences").get(cbg.add(createMyMenuBarCallback())); } PluginLoader.load(hpd.plugins, + hpd.pluginsLoadTimeout, cbg.addFinal(new GerritCallback<VoidResult>() { @Override public void onSuccess(VoidResult result) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java index d5805ef..94198cb 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
@@ -58,11 +58,12 @@ final SuggestBox suggestBox = new SuggestBox( new RemoteSuggestOracle(new SearchSuggestOracle()), searchBox, suggestionDisplay); - searchBox.setStyleName("gwt-TextBox"); + searchBox.setStyleName("searchTextBox"); searchBox.setVisibleLength(70); searchBox.setHintText(Gerrit.C.searchHint()); final Button searchButton = new Button(Gerrit.C.searchButton()); + searchButton.setStyleName("searchButton"); searchButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PluginLoader.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PluginLoader.java index f0fb436..ceb0eee 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PluginLoader.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/PluginLoader.java
@@ -32,15 +32,14 @@ /** Loads JavaScript plugins with a progress meter visible. */ public class PluginLoader extends DialogBox { - private static final int MAX_LOAD_TIME_MILLIS = 5000; private static PluginLoader self; public static void load(List<String> plugins, - AsyncCallback<VoidResult> callback) { + int loadTimeout, AsyncCallback<VoidResult> callback) { if (plugins == null || plugins.isEmpty()) { callback.onSuccess(VoidResult.create()); } else { - self = new PluginLoader(callback); + self = new PluginLoader(loadTimeout, callback); self.load(plugins); self.startTimers(); self.center(); @@ -51,6 +50,7 @@ self.loadedOne(); } + private final int loadTimeout; private final AsyncCallback<VoidResult> callback; private ProgressBar progress; private Timer show; @@ -58,9 +58,10 @@ private Timer timeout; private boolean visible; - private PluginLoader(AsyncCallback<VoidResult> cb) { + private PluginLoader(int loadTimeout, AsyncCallback<VoidResult> cb) { super(/* auto hide */false, /* modal */true); callback = cb; + this.loadTimeout = loadTimeout; progress = new ProgressBar(Gerrit.C.loadingPlugins()); setStyleName(Gerrit.RESOURCES.css().errorDialog()); @@ -98,7 +99,7 @@ @Override public void run() { - progress.setValue(100 * ++cycle * 250 / MAX_LOAD_TIME_MILLIS); + progress.setValue(100 * ++cycle * 250 / loadTimeout); } }; update.scheduleRepeating(250); @@ -109,7 +110,7 @@ finish(); } }; - timeout.schedule(MAX_LOAD_TIME_MILLIS); + timeout.schedule(loadTimeout); } private void loadedOne() {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java index 525684d..37b90c4 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java
@@ -65,7 +65,6 @@ private String message; private String branch; private String key; - private boolean canSubmit; Actions() { initWidget(uiBinder.createAndBindUi(this)); @@ -87,7 +86,12 @@ changeInfo = info; initChangeActions(info, hasUser); - initRevisionActions(info, revInfo, hasUser); + + NativeMap<ActionInfo> actionMap = revInfo.has_actions() + ? revInfo.actions() + : NativeMap.<ActionInfo> create(); + actionMap.copyKeysIntoChildren("id"); + reloadRevisionActions(actionMap); } private void initChangeActions(ChangeInfo info, boolean hasUser) { @@ -107,30 +111,29 @@ } } - private void initRevisionActions(ChangeInfo info, RevisionInfo revInfo, - boolean hasUser) { - NativeMap<ActionInfo> actions = revInfo.has_actions() - ? revInfo.actions() - : NativeMap.<ActionInfo> create(); - actions.copyKeysIntoChildren("id"); + void reloadRevisionActions(NativeMap<ActionInfo> actions) { + if (!Gerrit.isSignedIn()) { + return; + } + boolean canSubmit = actions.containsKey("submit"); + if (canSubmit) { + ActionInfo action = actions.get("submit"); + submit.setTitle(action.title()); + submit.setEnabled(action.enabled()); + submit.setHTML(new SafeHtmlBuilder() + .openDiv() + .append(action.label()) + .closeDiv()); + submit.setEnabled(action.enabled()); + } + submit.setVisible(canSubmit); - canSubmit = false; - if (hasUser) { - canSubmit = actions.containsKey("submit"); - if (canSubmit) { - ActionInfo action = actions.get("submit"); - submit.setTitle(action.title()); - submit.setEnabled(action.enabled()); - submit.setHTML(new SafeHtmlBuilder() - .openDiv() - .append(action.label()) - .closeDiv()); - } - a2b(actions, "cherrypick", cherrypick); - a2b(actions, "rebase", rebase); - for (String id : filterNonCore(actions)) { - add(new ActionButton(info, revInfo, actions.get(id))); - } + a2b(actions, "cherrypick", cherrypick); + a2b(actions, "rebase", rebase); + + RevisionInfo revInfo = changeInfo.revision(revision); + for (String id : filterNonCore(actions)) { + add(new ActionButton(changeInfo, revInfo, actions.get(id))); } } @@ -146,10 +149,6 @@ return ids; } - void setSubmitEnabled() { - submit.setVisible(canSubmit); - } - @UiHandler("followUp") void onFollowUp(@SuppressWarnings("unused") ClickEvent e) { if (followUpAction == null) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java index 8a27fd0..a6635f3 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java
@@ -134,8 +134,6 @@ private CommentLinkProcessor commentLinkProcessor; private EditInfo edit; - private KeyCommandSet keysNavigation; - private KeyCommandSet keysAction; private List<HandlerRegistration> handlers = new ArrayList<>(4); private UpdateCheckTimer updateCheck; private Timestamp lastDisplayedUpdate; @@ -248,7 +246,7 @@ void loadChangeInfo(boolean fg, AsyncCallback<ChangeInfo> cb) { RestApi call = ChangeApi.detail(changeId.get()); ChangeList.addOptions(call, EnumSet.of( - ListChangesOption.CURRENT_ACTIONS, + ListChangesOption.CHANGE_ACTIONS, ListChangesOption.ALL_REVISIONS)); if (!fg) { call.background(); @@ -256,6 +254,18 @@ call.get(cb); } + void loadRevisionInfo() { + RestApi call = ChangeApi.actions(changeId.get(), revision); + call.background(); + call.get(new GerritCallback<NativeMap<ActionInfo>>() { + @Override + public void onSuccess(NativeMap<ActionInfo> actionMap) { + actionMap.copyKeysIntoChildren("id"); + renderRevisionInfo(changeInfo, actionMap); + } + }); + } + @Override protected void onUnload() { if (replyAction != null) { @@ -281,69 +291,6 @@ labels.init(style); reviewers.init(style, ccText); hashtags.init(style); - - keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation()); - keysNavigation.add(new KeyCommand(0, 'u', Util.C.upToChangeList()) { - @Override - public void onKeyPress(final KeyPressEvent event) { - Gerrit.displayLastChangeList(); - } - }); - keysNavigation.add(new KeyCommand(0, 'R', Util.C.keyReloadChange()) { - @Override - public void onKeyPress(final KeyPressEvent event) { - Gerrit.display(PageLinks.toChange(changeId)); - } - }); - keysNavigation.add(new KeyCommand(0, 'n', Util.C.keyNextPatchSet()) { - @Override - public void onKeyPress(final KeyPressEvent event) { - gotoSibling(1); - } - }, new KeyCommand(0, 'p', Util.C.keyPreviousPatchSet()) { - @Override - public void onKeyPress(final KeyPressEvent event) { - gotoSibling(-1); - } - }); - - keysAction = new KeyCommandSet(Gerrit.C.sectionActions()); - keysAction.add(new KeyCommand(0, 'a', Util.C.keyPublishComments()) { - @Override - public void onKeyPress(KeyPressEvent event) { - if (Gerrit.isSignedIn()) { - onReply(null); - } else { - Gerrit.doSignIn(getToken()); - } - } - }); - keysAction.add(new KeyCommand(0, 'x', Util.C.keyExpandAllMessages()) { - @Override - public void onKeyPress(KeyPressEvent event) { - onExpandAll(null); - } - }); - keysAction.add(new KeyCommand(0, 'z', Util.C.keyCollapseAllMessages()) { - @Override - public void onKeyPress(KeyPressEvent event) { - onCollapseAll(null); - } - }); - if (Gerrit.isSignedIn()) { - keysAction.add(new KeyCommand(0, 's', Util.C.changeTableStar()) { - @Override - public void onKeyPress(KeyPressEvent event) { - star.setValue(!star.getValue(), true); - } - }); - keysAction.add(new KeyCommand(0, 'c', Util.C.keyAddReviewers()) { - @Override - public void onKeyPress(KeyPressEvent event) { - reviewers.onOpenForm(); - } - }); - } } private void initReplyButton(ChangeInfo info, String revision) { @@ -403,7 +350,8 @@ } } - private void initRevisionsAction(ChangeInfo info, String revision) { + private void initRevisionsAction(ChangeInfo info, String revision, + NativeMap<ActionInfo> actions) { int currentPatchSet; if (info.current_revision() != null && info.revisions().containsKey(info.current_revision())) { @@ -431,11 +379,6 @@ RevisionInfo revInfo = info.revision(revision); if (revInfo.draft()) { - NativeMap<ActionInfo> actions = revInfo.has_actions() - ? revInfo.actions() - : NativeMap.<ActionInfo> create(); - actions.copyKeysIntoChildren("id"); - if (actions.containsKey("publish")) { publish.setVisible(true); publish.setTitle(actions.get("publish").title()); @@ -566,7 +509,88 @@ @Override public void registerKeys() { super.registerKeys(); + + KeyCommandSet keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation()); + keysNavigation.add(new KeyCommand(0, 'u', Util.C.upToChangeList()) { + @Override + public void onKeyPress(final KeyPressEvent event) { + Gerrit.displayLastChangeList(); + } + }); + keysNavigation.add(new KeyCommand(0, 'R', Util.C.keyReloadChange()) { + @Override + public void onKeyPress(final KeyPressEvent event) { + Gerrit.display(PageLinks.toChange(changeId)); + } + }); + keysNavigation.add(new KeyCommand(0, 'n', Util.C.keyNextPatchSet()) { + @Override + public void onKeyPress(final KeyPressEvent event) { + gotoSibling(1); + } + }, new KeyCommand(0, 'p', Util.C.keyPreviousPatchSet()) { + @Override + public void onKeyPress(final KeyPressEvent event) { + gotoSibling(-1); + } + }); handlers.add(GlobalKey.add(this, keysNavigation)); + + KeyCommandSet keysAction = new KeyCommandSet(Gerrit.C.sectionActions()); + keysAction.add(new KeyCommand(0, 'a', Util.C.keyPublishComments()) { + @Override + public void onKeyPress(KeyPressEvent event) { + if (Gerrit.isSignedIn()) { + onReply(null); + } else { + Gerrit.doSignIn(getToken()); + } + } + }); + keysAction.add(new KeyCommand(0, 'x', Util.C.keyExpandAllMessages()) { + @Override + public void onKeyPress(KeyPressEvent event) { + onExpandAll(null); + } + }); + keysAction.add(new KeyCommand(0, 'z', Util.C.keyCollapseAllMessages()) { + @Override + public void onKeyPress(KeyPressEvent event) { + onCollapseAll(null); + } + }); + keysAction.add(new KeyCommand(0, 's', Util.C.changeTableStar()) { + @Override + public void onKeyPress(KeyPressEvent event) { + if (Gerrit.isSignedIn()) { + star.setValue(!star.getValue(), true); + } else { + Gerrit.doSignIn(getToken()); + } + } + }); + keysAction.add(new KeyCommand(0, 'c', Util.C.keyAddReviewers()) { + @Override + public void onKeyPress(KeyPressEvent event) { + if (Gerrit.isSignedIn()) { + reviewers.onOpenForm(); + } else { + Gerrit.doSignIn(getToken()); + } + } + }); + keysAction.add(new KeyCommand(0, 't', Util.C.keyEditTopic()) { + @Override + public void onKeyPress(KeyPressEvent event) { + if (Gerrit.isSignedIn()) { + if (topic.canEdit()) { + topic.onEdit(); + } + } else { + Gerrit.doSignIn(getToken()); + } + } + }); handlers.add(GlobalKey.add(this, keysAction)); files.registerKeys(); } @@ -806,6 +830,7 @@ commentLinkProcessor = result.getCommentLinkProcessor(); setTheme(result.getTheme()); renderChangeInfo(info); + loadRevisionInfo(); } })); } @@ -933,7 +958,6 @@ private void loadSubmitType(final Change.Status status, final boolean canSubmit) { if (canSubmit) { - actions.setSubmitEnabled(); if (status == Change.Status.NEW) { statusText.setInnerText(Util.C.readyToSubmit()); } @@ -1043,19 +1067,7 @@ private void renderChangeInfo(ChangeInfo info) { changeInfo = info; lastDisplayedUpdate = info.updated(); - RevisionInfo revisionInfo = info.revision(revision); - boolean current = info.status().isOpen() - && revision.equals(info.current_revision()) - && !revisionInfo.is_edit(); - if (revisionInfo.is_edit()) { - statusText.setInnerText(Util.C.changeEdit()); - } else if (!current && info.status() == Change.Status.NEW) { - statusText.setInnerText(Util.C.notCurrent()); - labels.setVisible(false); - } else { - statusText.setInnerText(Util.toLongString(info.status())); - } labels.set(info); renderOwner(info); @@ -1064,7 +1076,6 @@ initReplyButton(info, revision); initIncludedInAction(info); initChangeAction(info); - initRevisionsAction(info, revision); initDownloadAction(info, revision); initProjectLinks(info); initBranchLink(info); @@ -1084,17 +1095,44 @@ setVisible(hashtagTableRow, false); } + StringBuilder sb = new StringBuilder(); + sb.append(Util.M.changeScreenTitleId(info.id_abbreviated())); + if (info.subject() != null) { + sb.append(": "); + sb.append(info.subject()); + } + setWindowTitle(sb.toString()); + + // Properly render revision actions initially while waiting for + // the callback to populate them correctly. + NativeMap<ActionInfo> emptyMap = NativeMap.<ActionInfo> create(); + initRevisionsAction(info, revision, emptyMap); + quickApprove.setVisible(false); + setVisible(strategy, false); + actions.reloadRevisionActions(emptyMap); + } + + private void renderRevisionInfo(ChangeInfo info, + NativeMap<ActionInfo> actionMap) { + RevisionInfo revisionInfo = info.revision(revision); + boolean current = info.status().isOpen() + && revision.equals(info.current_revision()) + && !revisionInfo.is_edit(); + + if (revisionInfo.is_edit()) { + statusText.setInnerText(Util.C.changeEdit()); + } else if (!current && info.status() == Change.Status.NEW) { + statusText.setInnerText(Util.C.notCurrent()); + labels.setVisible(false); + } else { + statusText.setInnerText(Util.toLongString(info.status())); + } + + initRevisionsAction(info, revision, actionMap); + if (Gerrit.isSignedIn()) { replyAction = new ReplyAction(info, revision, style, commentLinkProcessor, reply, quickApprove); - if (topic.canEdit()) { - keysAction.add(new KeyCommand(0, 't', Util.C.keyEditTopic()) { - @Override - public void onKeyPress(KeyPressEvent event) { - topic.onEdit(); - } - }); - } } history.set(commentLinkProcessor, replyAction, changeId, info); @@ -1105,14 +1143,7 @@ quickApprove.setVisible(false); setVisible(strategy, false); } - - StringBuilder sb = new StringBuilder(); - sb.append(Util.M.changeScreenTitleId(info.id_abbreviated())); - if (info.subject() != null) { - sb.append(": "); - sb.append(info.subject()); - } - setWindowTitle(sb.toString()); + actions.reloadRevisionActions(actionMap); } private void renderOwner(ChangeInfo info) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java index 6638dbe..d66b84d 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java
@@ -101,6 +101,7 @@ input.label(qName, qValue); replyAction = action; setText(qName + qValueStr); + setVisible(true); } else { setVisible(false); }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java index 98595e7..1135491 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java
@@ -95,6 +95,13 @@ return call(id, "detail"); } + public static RestApi actions(int id, String revision) { + if (revision == null || revision.equals("")) { + revision = "current"; + } + return call(id, revision, "actions"); + } + public static void edit(int id, AsyncCallback<EditInfo> cb) { edit(id).get(cb); }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css index 8d961ca..9777508 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
@@ -297,13 +297,22 @@ white-space: nowrap; display: inline; } -.searchPanel .gwt-TextBox { +.searchPanel .searchTextBox { font-size: 9pt; + margin: 5.286px 3px 0 0; } -.searchPanel .gwt-Button { - font-size: 9pt; - margin-left: 2px; - padding: 3px 6px; +.searchPanel .searchButton { + text-align: center; + font-size: 8pt; + font-weight: bold; + cursor: pointer; + border: 2px solid; + color: #FFF; + border-color: rgba(0, 0, 0, 0.15); + height: 14px; + background-color: #20CA60; + -webkit-border-radius: 2px; + -webkit-box-sizing: content-box; } .suggestBoxPopup { z-index: 200;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java index 9d47977..7b88acf 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java
@@ -14,6 +14,9 @@ package com.google.gerrit.httpd; +import static java.nio.file.Files.isExecutable; +import static java.nio.file.Files.isRegularFile; + import com.google.gerrit.common.data.GitWebType; import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.SitePaths; @@ -23,16 +26,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; public class GitWebConfig { private static final Logger log = LoggerFactory.getLogger(GitWebConfig.class); private final String url; - private final File gitweb_cgi; - private final File gitweb_css; - private final File gitweb_js; - private final File git_logo_png; + private final Path gitweb_cgi; + private final Path gitweb_css; + private final Path gitweb_js; + private final Path git_logo_png; private GitWebType type; @Inject @@ -117,20 +121,20 @@ return; } - final File pkgCgi = new File("/usr/lib/cgi-bin/gitweb.cgi"); + final Path pkgCgi = Paths.get("/usr/lib/cgi-bin/gitweb.cgi"); String[] resourcePaths = {"/usr/share/gitweb/static", "/usr/share/gitweb", "/var/www/static", "/var/www"}; - File cgi; + Path cgi; if (cfgCgi != null) { // Use the CGI script configured by the administrator, failing if it // cannot be used as specified. // cgi = sitePaths.resolve(cfgCgi); - if (!cgi.isFile()) { + if (!isRegularFile(cgi)) { throw new IllegalStateException("Cannot find gitweb.cgi: " + cgi); } - if (!cgi.canExecute()) { + if (!isExecutable(cgi)) { throw new IllegalStateException("Cannot execute gitweb.cgi: " + cgi); } @@ -138,11 +142,11 @@ // Assume the administrator pointed us to the distribution, // which also has the corresponding CSS and logo file. // - String absPath = cgi.getParentFile().getAbsolutePath(); + String absPath = cgi.getParent().toAbsolutePath().toString(); resourcePaths = new String[] {absPath + "/static", absPath}; } - } else if (pkgCgi.isFile() && pkgCgi.canExecute()) { + } else if (isRegularFile(pkgCgi) && isExecutable(pkgCgi)) { // Use the OS packaged CGI. // log.debug("Assuming gitweb at " + pkgCgi); @@ -154,13 +158,13 @@ resourcePaths = new String[] {}; } - File css = null, js = null, logo = null; + Path css = null, js = null, logo = null; for (String path : resourcePaths) { - File dir = new File(path); - css = new File(dir, "gitweb.css"); - js = new File(dir, "gitweb.js"); - logo = new File(dir, "git-logo.png"); - if (css.isFile() && logo.isFile()) { + Path dir = Paths.get(path); + css = dir.resolve("gitweb.css"); + js = dir.resolve("gitweb.js"); + logo = dir.resolve("git-logo.png"); + if (isRegularFile(css) && isRegularFile(logo)) { break; } } @@ -191,22 +195,22 @@ } /** @return local path to the CGI executable; null if we shouldn't execute. */ - public File getGitwebCGI() { + public Path getGitwebCGI() { return gitweb_cgi; } /** @return local path of the {@code gitweb.css} matching the CGI. */ - public File getGitwebCSS() { + public Path getGitwebCSS() { return gitweb_css; } /** @return local path of the {@code gitweb.js} for the CGI. */ - public File getGitwebJS() { + public Path getGitwebJS() { return gitweb_js; } /** @return local path of the {@code git-logo.png} for the CGI. */ - public File getGitLogoPNG() { + public Path getGitLogoPNG() { return git_logo_png; }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HtmlDomUtil.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HtmlDomUtil.java index 1a2d3f6..1eb88b1 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HtmlDomUtil.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HtmlDomUtil.java
@@ -14,6 +14,8 @@ package com.google.gerrit.httpd; +import com.google.common.io.ByteStreams; + import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -21,14 +23,14 @@ import org.xml.sax.SAXException; import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.StringWriter; -import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.util.zip.GZIPOutputStream; import javax.xml.parsers.DocumentBuilder; @@ -36,7 +38,6 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; @@ -49,21 +50,21 @@ /** Utility functions to deal with HTML using W3C DOM operations. */ public class HtmlDomUtil { /** Standard character encoding we prefer (UTF-8). */ - public static final String ENC = "UTF-8"; + public static final Charset ENC = StandardCharsets.UTF_8; /** DOCTYPE for a standards mode HTML document. */ public static final String HTML_STRICT = "-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd"; /** Convert a document to a UTF-8 byte sequence. */ - public static byte[] toUTF8(final Document hostDoc) throws IOException { + public static byte[] toUTF8(Document hostDoc) throws IOException { return toString(hostDoc).getBytes(ENC); } /** Compress the document. */ - public static byte[] compress(final byte[] raw) throws IOException { - final ByteArrayOutputStream out = new ByteArrayOutputStream(); - final GZIPOutputStream gz = new GZIPOutputStream(out); + public static byte[] compress(byte[] raw) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + GZIPOutputStream gz = new GZIPOutputStream(out); gz.write(raw); gz.finish(); gz.flush(); @@ -71,43 +72,39 @@ } /** Convert a document to a String, assuming later encoding to UTF-8. */ - public static String toString(final Document hostDoc) throws IOException { + public static String toString(Document hostDoc) throws IOException { try { - final StringWriter out = new StringWriter(); - final DOMSource domSource = new DOMSource(hostDoc); - final StreamResult streamResult = new StreamResult(out); - final TransformerFactory tf = TransformerFactory.newInstance(); - final Transformer serializer = tf.newTransformer(); - serializer.setOutputProperty(OutputKeys.ENCODING, ENC); + StringWriter out = new StringWriter(); + DOMSource domSource = new DOMSource(hostDoc); + StreamResult streamResult = new StreamResult(out); + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer serializer = tf.newTransformer(); + serializer.setOutputProperty(OutputKeys.ENCODING, ENC.name()); serializer.setOutputProperty(OutputKeys.METHOD, "html"); serializer.setOutputProperty(OutputKeys.INDENT, "no"); serializer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, HtmlDomUtil.HTML_STRICT); serializer.transform(domSource, streamResult); return out.toString(); - } catch (TransformerConfigurationException e) { - final IOException r = new IOException("Error transforming page"); - r.initCause(e); - throw r; } catch (TransformerException e) { - final IOException r = new IOException("Error transforming page"); + IOException r = new IOException("Error transforming page"); r.initCause(e); throw r; } } /** Find an element by its "id" attribute; null if no element is found. */ - public static Element find(final Node parent, final String name) { - final NodeList list = parent.getChildNodes(); + public static Element find(Node parent, String name) { + NodeList list = parent.getChildNodes(); for (int i = 0; i < list.getLength(); i++) { - final Node n = list.item(i); + Node n = list.item(i); if (n instanceof Element) { - final Element e = (Element) n; + Element e = (Element) n; if (name.equals(e.getAttribute("id"))) { return e; } } - final Element r = find(n, name); + Element r = find(n, name); if (r != null) { return r; } @@ -116,9 +113,8 @@ } /** Append an HTML <input type="hidden"> to the form. */ - public static void addHidden(final Element form, final String name, - final String value) { - final Element in = form.getOwnerDocument().createElement("input"); + public static void addHidden(Element form, String name, String value) { + Element in = form.getOwnerDocument().createElement("input"); in.setAttribute("type", "hidden"); in.setAttribute("name", name); in.setAttribute("value", value); @@ -135,51 +131,38 @@ } /** Clone a document so it can be safely modified on a per-request basis. */ - public static Document clone(final Document doc) throws IOException { - final Document d; + public static Document clone(Document doc) throws IOException { + Document d; try { d = newBuilder().newDocument(); } catch (ParserConfigurationException e) { throw new IOException("Cannot clone document"); } - final Node n = d.importNode(doc.getDocumentElement(), true); + Node n = d.importNode(doc.getDocumentElement(), true); d.appendChild(n); return d; } /** Parse an XHTML file from our CLASSPATH and return the instance. */ - public static Document parseFile(final Class<?> context, final String name) + public static Document parseFile(Class<?> context, String name) throws IOException { - final InputStream in; - - in = context.getResourceAsStream(name); - if (in == null) { - return null; - } - try { - try { - try { - final Document doc = newBuilder().parse(in); - compact(doc); - return doc; - } catch (SAXException e) { - throw new IOException("Error reading " + name, e); - } catch (ParserConfigurationException e) { - throw new IOException("Error reading " + name, e); - } - } finally { - in.close(); + try (InputStream in = context.getResourceAsStream(name)) { + if (in == null) { + return null; } - } catch (IOException e) { + Document doc = newBuilder().parse(in); + compact(doc); + return doc; + } catch (SAXException | ParserConfigurationException | IOException e) { throw new IOException("Error reading " + name, e); } } - private static void compact(final Document doc) { + private static void compact(Document doc) { try { - final String expr = "//text()[normalize-space(.) = '']"; - final XPathFactory xp = XPathFactory.newInstance(); - final XPathExpression e = xp.newXPath().compile(expr); + String expr = "//text()[normalize-space(.) = '']"; + XPathFactory xp = XPathFactory.newInstance(); + XPathExpression e = xp.newXPath().compile(expr); NodeList empty = (NodeList) e.evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < empty.getLength(); i++) { Node node = empty.item(i); @@ -191,78 +174,50 @@ } /** Read a Read a UTF-8 text file from our CLASSPATH and return it. */ - public static String readFile(final Class<?> context, final String name) + public static String readFile(Class<?> context, String name) throws IOException { - final InputStream in = context.getResourceAsStream(name); - if (in == null) { - return null; - } - try { - return asString(in); + try (InputStream in = context.getResourceAsStream(name)) { + if (in == null) { + return null; + } + return new String(ByteStreams.toByteArray(in), ENC); } catch (IOException e) { throw new IOException("Error reading " + name, e); } } /** Parse an XHTML file from the local drive and return the instance. */ - public static Document parseFile(final File path) throws IOException { - try { - final InputStream in = new FileInputStream(path); - try { - try { - final Document doc = newBuilder().parse(in); - compact(doc); - return doc; - } catch (SAXException e) { - throw new IOException("Error reading " + path, e); - } catch (ParserConfigurationException e) { - throw new IOException("Error reading " + path, e); - } - } finally { - in.close(); - } - } catch (FileNotFoundException e) { + public static Document parseFile(Path path) throws IOException { + try (InputStream in = Files.newInputStream(path)) { + Document doc = newBuilder().parse(in); + compact(doc); + return doc; + } catch (NoSuchFileException e) { return null; - } catch (IOException e) { + } catch (SAXException | ParserConfigurationException | IOException e) { throw new IOException("Error reading " + path, e); } } /** Read a UTF-8 text file from the local drive. */ - public static String readFile(final File parentDir, final String name) + public static String readFile(Path parentDir, String name) throws IOException { if (parentDir == null) { return null; } - final File path = new File(parentDir, name); - try { - return asString(new FileInputStream(path)); - } catch (FileNotFoundException e) { + Path path = parentDir.resolve(name); + try (InputStream in = Files.newInputStream(path)) { + return new String(ByteStreams.toByteArray(in), ENC); + } catch (NoSuchFileException e) { return null; } catch (IOException e) { throw new IOException("Error reading " + path, e); } } - private static String asString(final InputStream in) - throws UnsupportedEncodingException, IOException { - try { - final StringBuilder w = new StringBuilder(); - final InputStreamReader r = new InputStreamReader(in, ENC); - final char[] buf = new char[512]; - int n; - while ((n = r.read(buf)) > 0) { - w.append(buf, 0, n); - } - return w.toString(); - } finally { - in.close(); - } - } - private static DocumentBuilder newBuilder() throws ParserConfigurationException { - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(false); factory.setExpandEntityReferences(false); factory.setIgnoringComments(true);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java index b8a8092..ed84caf 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
@@ -104,7 +104,7 @@ throw new ServletException(e); } rsp.setContentType("text/html"); - rsp.setCharacterEncoding(HtmlDomUtil.ENC); + rsp.setCharacterEncoding(HtmlDomUtil.ENC.name()); rsp.setContentLength(raw.length); final OutputStream out = rsp.getOutputStream(); try { @@ -138,7 +138,7 @@ } else { rsp.setContentType("text/html"); - rsp.setCharacterEncoding(HtmlDomUtil.ENC); + rsp.setCharacterEncoding(HtmlDomUtil.ENC.name()); final Writer out = rsp.getWriter(); out.write("<html>"); out.write("<body>");
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java index 19c8342..b5400b2 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java
@@ -110,7 +110,7 @@ CacheHeaders.setNotCacheable(rsp); rsp.setContentType("text/html"); - rsp.setCharacterEncoding(HtmlDomUtil.ENC); + rsp.setCharacterEncoding(HtmlDomUtil.ENC.name()); rsp.setContentLength(tosend.length); final OutputStream out = rsp.getOutputStream(); try {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitLogoServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitLogoServlet.java index 41aa552..3396f2b 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitLogoServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitLogoServlet.java
@@ -14,16 +14,19 @@ package com.google.gerrit.httpd.gitweb; +import static com.google.gerrit.common.FileUtil.lastModified; + +import com.google.common.io.ByteStreams; import com.google.gerrit.httpd.GitWebConfig; import com.google.gwtexpui.server.CacheHeaders; import com.google.inject.Inject; import com.google.inject.Singleton; -import org.eclipse.jgit.util.IO; - -import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.util.concurrent.TimeUnit; import javax.servlet.ServletOutputStream; @@ -38,16 +41,16 @@ private final byte[] raw; @Inject - GitLogoServlet(final GitWebConfig gitWebConfig) throws IOException { + GitLogoServlet(GitWebConfig gitWebConfig) throws IOException { byte[] png; - final File src = gitWebConfig.getGitLogoPNG(); + Path src = gitWebConfig.getGitLogoPNG(); if (src != null) { - try { - png = IO.readFully(src); - } catch (FileNotFoundException e) { + try (InputStream in = Files.newInputStream(src)) { + png = ByteStreams.toByteArray(in); + } catch (NoSuchFileException e) { png = null; } - modified = src.lastModified(); + modified = lastModified(src); } else { modified = -1; png = null;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java index 4a39b97..5625334 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java
@@ -14,6 +14,8 @@ package com.google.gerrit.httpd.gitweb; +import static com.google.gerrit.common.FileUtil.lastModified; + import com.google.gerrit.httpd.GitWebConfig; import com.google.gerrit.httpd.HtmlDomUtil; import com.google.gerrit.server.config.SitePaths; @@ -22,8 +24,8 @@ import com.google.inject.Inject; import com.google.inject.Singleton; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.concurrent.TimeUnit; import javax.servlet.ServletOutputStream; @@ -55,14 +57,14 @@ private final byte[] raw_css; private final byte[] gz_css; - GitWebCssServlet(final File src) + GitWebCssServlet(final Path src) throws IOException { if (src != null) { - final File dir = src.getParentFile(); - final String name = src.getName(); + final Path dir = src.getParent(); + final String name = src.getFileName().toString(); final String raw = HtmlDomUtil.readFile(dir, name); if (raw != null) { - modified = src.lastModified(); + modified = lastModified(src); raw_css = raw.getBytes(ENC); gz_css = HtmlDomUtil.compress(raw_css); } else {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebJavaScriptServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebJavaScriptServlet.java index d71732a..6926afd 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebJavaScriptServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebJavaScriptServlet.java
@@ -14,16 +14,19 @@ package com.google.gerrit.httpd.gitweb; +import static com.google.gerrit.common.FileUtil.lastModified; + +import com.google.common.io.ByteStreams; import com.google.gerrit.httpd.GitWebConfig; import com.google.gwtexpui.server.CacheHeaders; import com.google.inject.Inject; import com.google.inject.Singleton; -import org.eclipse.jgit.util.IO; - -import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.util.concurrent.TimeUnit; import javax.servlet.ServletOutputStream; @@ -40,14 +43,14 @@ @Inject GitWebJavaScriptServlet(final GitWebConfig gitWebConfig) throws IOException { byte[] png; - final File src = gitWebConfig.getGitwebJS(); + Path src = gitWebConfig.getGitwebJS(); if (src != null) { - try { - png = IO.readFully(src); - } catch (FileNotFoundException e) { + try (InputStream in = Files.newInputStream(src)) { + png = ByteStreams.toByteArray(in); + } catch (NoSuchFileException e) { png = null; } - modified = src.lastModified(); + modified = lastModified(src); } else { modified = -1; png = null;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java index 32fbe96..fd8d3b4 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java
@@ -29,6 +29,8 @@ package com.google.gerrit.httpd.gitweb; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.data.GerritConfig; import com.google.gerrit.extensions.restapi.Url; @@ -55,7 +57,6 @@ import java.io.BufferedReader; import java.io.EOFException; import java.io.File; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -63,6 +64,8 @@ import java.io.PrintWriter; import java.net.URI; import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -84,7 +87,7 @@ private final Set<String> deniedActions; private final int bufferSize = 8192; - private final File gitwebCgi; + private final Path gitwebCgi; private final URI gitwebUrl; private final LocalDiskRepositoryManager repoManager; private final ProjectControl.Factory projectControl; @@ -145,26 +148,28 @@ private void makeSiteConfig(final SitePaths site, final GerritConfig gerritConfig) throws IOException { - if (!site.tmp_dir.exists()) { - site.tmp_dir.mkdirs(); + if (!Files.exists(site.tmp_dir)) { + Files.createDirectories(site.tmp_dir); } - File myconf = File.createTempFile("gitweb_config", ".perl", site.tmp_dir); + Path myconf = Files.createTempFile(site.tmp_dir, "gitweb_config", ".perl"); // To make our configuration file only readable or writable by us; // this reduces the chances of someone tampering with the file. // - myconf.setWritable(false, false /* all */); - myconf.setReadable(false, false /* all */); - myconf.setExecutable(false, false /* all */); + // TODO(dborowitz): Is there a portable way to do this with NIO? + File myconfFile = myconf.toFile(); + myconfFile.setWritable(false, false /* all */); + myconfFile.setReadable(false, false /* all */); + myconfFile.setExecutable(false, false /* all */); - myconf.setWritable(true, true /* owner only */); - myconf.setReadable(true, true /* owner only */); + myconfFile.setWritable(true, true /* owner only */); + myconfFile.setReadable(true, true /* owner only */); _env.set("GIT_DIR", "."); - _env.set("GITWEB_CONFIG", myconf.getAbsolutePath()); + _env.set("GITWEB_CONFIG", myconf.toAbsolutePath().toString()); - final PrintWriter p = new PrintWriter(new FileWriter(myconf)); - try { + try (PrintWriter p = + new PrintWriter(Files.newBufferedWriter(myconf, UTF_8))) { p.print("# Autogenerated by Gerrit Code Review \n"); p.print("# DO NOT EDIT\n"); p.print("\n"); @@ -172,12 +177,12 @@ // We are mounted at the same level in the context as the main // UI, so we can include the same header and footer scheme. // - final File hdr = site.site_header; - if (hdr.isFile()) { + Path hdr = site.site_header; + if (Files.isRegularFile(hdr)) { p.print("$site_header = " + quoteForPerl(hdr) + ";\n"); } - final File ftr = site.site_footer; - if (ftr.isFile()) { + Path ftr = site.site_footer; + if (Files.isRegularFile(ftr)) { p.print("$site_footer = " + quoteForPerl(ftr) + ";\n"); } @@ -190,8 +195,8 @@ p.print("$logo = 'gitweb-logo.png';\n"); p.print("$javascript = 'gitweb.js';\n"); p.print("@stylesheets = ('gitweb-default.css');\n"); - final File css = site.site_css; - if (css.isFile()) { + Path css = site.site_css; + if (Files.isRegularFile(css)) { p.print("push @stylesheets, 'gitweb-site.css';\n"); } @@ -292,15 +297,15 @@ // If the administrator has created a site-specific gitweb_config, // load that before we perform any final overrides. // - final File sitecfg = site.site_gitweb; - if (sitecfg.isFile()) { + Path sitecfg = site.site_gitweb; + if (Files.isRegularFile(sitecfg)) { p.print("$GITWEB_CONFIG = " + quoteForPerl(sitecfg) + ";\n"); p.print("if (-e $GITWEB_CONFIG) {\n"); p.print(" do " + quoteForPerl(sitecfg) + ";\n"); p.print("}\n"); } - final File root = repoManager.getBasePath(); + Path root = repoManager.getBasePath(); p.print("$projectroot = " + quoteForPerl(root) + ";\n"); // Permit exporting only the project we were started for. @@ -324,18 +329,16 @@ // p.print("$feature{'forks'}{'override'} = 0;\n"); p.print("$feature{'forks'}{'default'} = [0];\n"); - } finally { - p.close(); } - myconf.setReadOnly(); + myconfFile.setReadOnly(); } - private String quoteForPerl(File value) { - return quoteForPerl(value.getAbsolutePath()); + private static String quoteForPerl(Path value) { + return quoteForPerl(value.toAbsolutePath().toString()); } - private String quoteForPerl(String value) { + private static String quoteForPerl(String value) { if (value == null || value.isEmpty()) { return "''"; } @@ -450,9 +453,10 @@ private void exec(final HttpServletRequest req, final HttpServletResponse rsp, final ProjectControl project) throws IOException { final Process proc = - Runtime.getRuntime().exec(new String[] {gitwebCgi.getAbsolutePath()}, + Runtime.getRuntime().exec( + new String[] {gitwebCgi.toAbsolutePath().toString()}, makeEnv(req, project), - gitwebCgi.getAbsoluteFile().getParentFile()); + gitwebCgi.toAbsolutePath().getParent().toFile()); copyStderrToLog(proc.getErrorStream()); if (0 < req.getContentLength()) { @@ -530,7 +534,7 @@ // env.set("REQUEST_METHOD", req.getMethod()); env.set("SCRIPT_NAME", req.getContextPath() + req.getServletPath()); - env.set("SCRIPT_FILENAME", gitwebCgi.getAbsolutePath()); + env.set("SCRIPT_FILENAME", gitwebCgi.toAbsolutePath().toString()); env.set("SERVER_NAME", req.getServerName()); env.set("SERVER_PORT", Integer.toString(req.getServerPort())); env.set("SERVER_PROTOCOL", req.getProtocol());
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java index 31ff107..fd26837 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/HttpPluginServlet.java
@@ -14,6 +14,7 @@ package com.google.gerrit.httpd.plugins; +import static com.google.gerrit.common.FileUtil.lastModified; import static com.google.gerrit.server.plugins.PluginEntry.ATTR_CHARACTER_ENCODING; import static com.google.gerrit.server.plugins.PluginEntry.ATTR_CONTENT_TYPE; @@ -24,6 +25,7 @@ import com.google.common.cache.Cache; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.io.ByteStreams; import com.google.common.net.HttpHeaders; import com.google.gerrit.extensions.registration.RegistrationHandle; import com.google.gerrit.httpd.resources.Resource; @@ -55,14 +57,14 @@ import org.slf4j.LoggerFactory; import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collections; import java.util.Enumeration; import java.util.List; @@ -303,7 +305,7 @@ } if (!entry.isPresent() && file.endsWith("/index.html")) { String pfx = file.substring(0, file.length() - "index.html".length()); - long pluginLastModified = holder.plugin.getSrcFile().lastModified(); + long pluginLastModified = lastModified(holder.plugin.getSrcFile()); if (hasUpToDateCachedResource(rsc, pluginLastModified)) { rsc.send(req, res); } else { @@ -608,12 +610,12 @@ private void sendJsPlugin(Plugin plugin, PluginResourceKey key, HttpServletRequest req, HttpServletResponse res) throws IOException { - File pluginFile = plugin.getSrcFile(); + Path path = plugin.getSrcFile(); if (req.getRequestURI().endsWith(getJsPluginPath(plugin)) - && pluginFile.exists()) { - res.setHeader("Content-Length", Long.toString(pluginFile.length())); + && Files.exists(path)) { + res.setHeader("Content-Length", Long.toString(Files.size(path))); res.setContentType("application/javascript"); - writeToResponse(res, new FileInputStream(pluginFile)); + writeToResponse(res, Files.newInputStream(path)); } else { resourceCache.put(key, Resource.NOT_FOUND); Resource.NOT_FOUND.send(req, res); @@ -621,25 +623,15 @@ } private static String getJsPluginPath(Plugin plugin) { - return String.format("/plugins/%s/static/%s", plugin.getName(), plugin.getSrcFile() - .getName()); + return String.format("/plugins/%s/static/%s", plugin.getName(), + plugin.getSrcFile().getFileName()); } - private void writeToResponse(HttpServletResponse res, InputStream in) + private void writeToResponse(HttpServletResponse res, InputStream inputStream) throws IOException { - try { - OutputStream out = res.getOutputStream(); - try { - byte[] tmp = new byte[1024]; - int n; - while ((n = in.read(tmp)) > 0) { - out.write(tmp, 0, n); - } - } finally { - out.close(); - } - } finally { - in.close(); + try (OutputStream out = res.getOutputStream(); + InputStream in = inputStream) { + ByteStreams.copy(in, out); } } @@ -671,9 +663,9 @@ } private static String getPrefix(Plugin plugin, String attr, String def) { - File srcFile = plugin.getSrcFile(); + Path path = plugin.getSrcFile(); PluginContentScanner scanner = plugin.getContentScanner(); - if (srcFile == null || scanner == PluginContentScanner.EMPTY) { + if (path == null || scanner == PluginContentScanner.EMPTY) { return def; } try {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/CatServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/CatServlet.java index dddcd67..72fc008 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/CatServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/CatServlet.java
@@ -202,32 +202,29 @@ final RevCommit fromCommit; final String suffix; final String path = patchKey.getFileName(); - try { - final ObjectReader reader = repo.newObjectReader(); - try { - final RevWalk rw = new RevWalk(reader); - final RevCommit c; - final TreeWalk tw; + try (ObjectReader reader = repo.newObjectReader(); + RevWalk rw = new RevWalk(reader)) { + final RevCommit c; - c = rw.parseCommit(ObjectId.fromString(revision)); - if (side == 0) { - fromCommit = c; - suffix = "new"; + c = rw.parseCommit(ObjectId.fromString(revision)); + if (side == 0) { + fromCommit = c; + suffix = "new"; - } else if (1 <= side && side - 1 < c.getParentCount()) { - fromCommit = rw.parseCommit(c.getParent(side - 1)); - if (c.getParentCount() == 1) { - suffix = "old"; - } else { - suffix = "old" + side; - } - + } else if (1 <= side && side - 1 < c.getParentCount()) { + fromCommit = rw.parseCommit(c.getParent(side - 1)); + if (c.getParentCount() == 1) { + suffix = "old"; } else { - rsp.sendError(HttpServletResponse.SC_NOT_FOUND); - return; + suffix = "old" + side; } - tw = TreeWalk.forPath(reader, path, fromCommit.getTree()); + } else { + rsp.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + + try (TreeWalk tw = TreeWalk.forPath(reader, path, fromCommit.getTree())) { if (tw == null) { rsp.sendError(HttpServletResponse.SC_NOT_FOUND); return; @@ -240,8 +237,6 @@ rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } - } finally { - reader.release(); } } catch (IOException e) { getServletContext().log("Cannot read repository", e);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java index 90c5ff4..f3895b8 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java
@@ -14,6 +14,8 @@ package com.google.gerrit.httpd.raw; +import static com.google.gerrit.common.FileUtil.lastModified; + import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.hash.Hasher; @@ -30,6 +32,7 @@ import com.google.gerrit.httpd.WebSession; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.IdentifiedUser; +import com.google.gerrit.server.config.ConfigUtil; import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.notedb.NotesMigration; @@ -47,14 +50,15 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringWriter; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import javax.servlet.ServletContext; import javax.servlet.ServletException; @@ -70,6 +74,7 @@ LoggerFactory.getLogger(HostPageServlet.class); private static final boolean IS_DEV = Boolean.getBoolean("Gerrit.GwtDevMode"); private static final String HPD_ID = "gerrit_hostpagedata"; + private static final int DEFAULT_JS_LOAD_TIMEOUT = 5000; private final Provider<CurrentUser> currentUser; private final DynamicItem<WebSession> session; @@ -84,6 +89,7 @@ private final boolean refreshHeaderFooter; private final StaticServlet staticServlet; private final boolean isNoteDbEnabled; + private final Integer pluginsLoadTimeout; private volatile Page page; @Inject @@ -107,6 +113,7 @@ refreshHeaderFooter = cfg.getBoolean("site", "refreshHeaderFooter", true); staticServlet = ss; isNoteDbEnabled = migration.enabled(); + pluginsLoadTimeout = getPluginsLoadTimeout(cfg); final String pageName = "HostPage.html"; template = HtmlDomUtil.parseFile(getClass(), pageName); @@ -154,22 +161,29 @@ page = new Page(); } + private static int getPluginsLoadTimeout(final Config cfg) { + long cfgValue = + ConfigUtil.getTimeUnit(cfg, "plugins", null, "jsLoadTimeout", + DEFAULT_JS_LOAD_TIMEOUT, TimeUnit.MILLISECONDS); + if (cfgValue < 0) { + return 0; + } + return (int) cfgValue; + } + private void json(final Object data, final StringWriter w) { JsonServlet.defaultGsonBuilder().create().toJson(data, w); } private Page get() { Page p = page; - if (refreshHeaderFooter && p.isStale()) { - final Page newPage; - try { - newPage = new Page(); - } catch (IOException e) { - log.error("Cannot refresh site header/footer", e); - return p; + try { + if (refreshHeaderFooter && p.isStale()) { + p = new Page(); + page = p; } - p = newPage; - page = p; + } catch (IOException e) { + log.error("Cannot refresh site header/footer", e); } return p; } @@ -216,7 +230,7 @@ CacheHeaders.setNotCacheable(rsp); rsp.setContentType("text/html"); - rsp.setCharacterEncoding(HtmlDomUtil.ENC); + rsp.setCharacterEncoding(HtmlDomUtil.ENC.name()); rsp.setContentLength(tosend.length); final OutputStream out = rsp.getOutputStream(); try { @@ -288,16 +302,16 @@ } private static class FileInfo { - private final File path; + private final Path path; private final long time; - FileInfo(final File p) { + FileInfo(Path p) { path = p; - time = path.lastModified(); + time = lastModified(path); } boolean isStale() { - return time != path.lastModified(); + return time != lastModified(path); } } @@ -319,6 +333,7 @@ pageData.version = Version.getVersion(); pageData.config = config; pageData.isNoteDbEnabled = isNoteDbEnabled; + pageData.pluginsLoadTimeout = pluginsLoadTimeout; final StringWriter w = new StringWriter(); w.write("var " + HPD_ID + "="); @@ -364,8 +379,8 @@ } } - private FileInfo injectCssFile(final Document hostDoc, final String id, - final File src) throws IOException { + private FileInfo injectCssFile(Document hostDoc, String id, Path src) + throws IOException { final FileInfo info = new FileInfo(src); final Element banner = HtmlDomUtil.find(hostDoc, id); if (banner == null) { @@ -376,7 +391,8 @@ banner.removeChild(banner.getFirstChild()); } - String css = HtmlDomUtil.readFile(src.getParentFile(), src.getName()); + String css = + HtmlDomUtil.readFile(src.getParent(), src.getFileName().toString()); if (css == null) { return info; } @@ -385,8 +401,8 @@ return info; } - private FileInfo injectXmlFile(final Document hostDoc, final String id, - final File src) throws IOException { + private FileInfo injectXmlFile(Document hostDoc, String id, Path src) + throws IOException { final FileInfo info = new FileInfo(src); final Element banner = HtmlDomUtil.find(hostDoc, id); if (banner == null) {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java index 9c267a8..00568f0 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java
@@ -68,7 +68,7 @@ CacheHeaders.setNotCacheable(rsp); rsp.setContentType("text/html"); - rsp.setCharacterEncoding(HtmlDomUtil.ENC); + rsp.setCharacterEncoding(HtmlDomUtil.ENC.name()); rsp.setContentLength(tosend.length); final OutputStream out = rsp.getOutputStream(); try {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/RobotsServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/RobotsServlet.java index 1d8e74d..2f5bc3a 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/RobotsServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/RobotsServlet.java
@@ -14,6 +14,9 @@ package com.google.gerrit.httpd.raw; +import static java.nio.file.Files.exists; +import static java.nio.file.Files.isReadable; + import com.google.common.io.ByteStreams; import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.SitePaths; @@ -24,11 +27,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -58,13 +61,13 @@ private static final Logger log = LoggerFactory.getLogger(RobotsServlet.class); - private final File robotsFile; + private final Path robotsFile; @Inject RobotsServlet(@GerritServerConfig final Config config, final SitePaths sitePaths) { - File file = sitePaths.resolve( + Path file = sitePaths.resolve( config.getString("httpd", null, "robotsFile")); - if (file != null && (!file.exists() || !file.canRead())) { + if (file != null && (!exists(file) || !isReadable(file))) { log.warn("Cannot read httpd.robotsFile, using default"); file = null; } @@ -75,23 +78,16 @@ protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp) throws IOException { rsp.setContentType("text/plain"); - InputStream in = openRobotsFile(); - try { - OutputStream out = rsp.getOutputStream(); - try { - ByteStreams.copy(in, out); - } finally { - out.close(); - } - } finally { - in.close(); + try (InputStream in = openRobotsFile(); + OutputStream out = rsp.getOutputStream()) { + ByteStreams.copy(in, out); } } private InputStream openRobotsFile() { if (robotsFile != null) { try { - return new FileInputStream(robotsFile); + return Files.newInputStream(robotsFile); } catch (IOException e) { log.warn("Cannot read " + robotsFile + "; using default", e); }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java index 52b7a5c9..93bcce8 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java
@@ -17,8 +17,11 @@ import static com.google.common.net.HttpHeaders.CONTENT_ENCODING; import static com.google.common.net.HttpHeaders.ETAG; import static com.google.common.net.HttpHeaders.IF_NONE_MATCH; +import static com.google.gerrit.common.FileUtil.lastModified; + import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.MINUTES; + import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED; @@ -30,7 +33,7 @@ import com.google.common.cache.Weigher; import com.google.common.collect.Maps; import com.google.common.hash.Hashing; -import com.google.common.io.ByteStreams; +import com.google.gerrit.common.FileUtil; import com.google.gerrit.common.Nullable; import com.google.gerrit.httpd.HtmlDomUtil; import com.google.gerrit.server.config.GerritServerConfig; @@ -44,11 +47,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -89,21 +92,19 @@ return type != null ? type : "application/octet-stream"; } - private final File staticBase; - private final String staticBasePath; + private final Path staticBase; private final boolean refresh; private final LoadingCache<String, Resource> cache; @Inject StaticServlet(@GerritServerConfig Config cfg, SitePaths site) { - File f; + Path p; try { - f = site.static_dir.getCanonicalFile(); + p = site.static_dir.toRealPath().normalize(); } catch (IOException e) { - f = site.static_dir.getAbsoluteFile(); + p = site.static_dir.toAbsolutePath().normalize(); } - staticBase = f; - staticBasePath = staticBase.getPath() + File.separator; + staticBase = p; refresh = cfg.getBoolean("site", "refreshHeaderFooter", true); cache = CacheBuilder.newBuilder() .maximumWeight(1 << 20) @@ -131,7 +132,8 @@ } } - private Resource getResource(HttpServletRequest req) throws ExecutionException { + private Resource getResource(HttpServletRequest req) + throws ExecutionException { String name = CharMatcher.is('/').trimFrom(req.getPathInfo()); if (isUnreasonableName(name)) { return Resource.NOT_FOUND; @@ -209,29 +211,22 @@ } private Resource loadResource(String name) throws IOException { - File p = new File(staticBase, name); + Path p = staticBase.resolve(name); try { - p = p.getCanonicalFile(); + p = p.toRealPath().normalize(); } catch (IOException e) { return Resource.NOT_FOUND; } - if (!p.getPath().startsWith(staticBasePath)) { + if (!p.startsWith(staticBase)) { return Resource.NOT_FOUND; } - long ts = p.lastModified(); - FileInputStream in; - try { - in = new FileInputStream(p); - } catch (FileNotFoundException e) { - return Resource.NOT_FOUND; - } - + long ts = FileUtil.lastModified(p); byte[] raw; try { - raw = ByteStreams.toByteArray(in); - } finally { - in.close(); + raw = Files.readAllBytes(p); + } catch (NoSuchFileException e) { + return Resource.NOT_FOUND; } return new Resource(p, ts, contentType(name), raw); } @@ -239,13 +234,13 @@ static class Resource { static final Resource NOT_FOUND = new Resource(null, -1, "", new byte[] {}); - final File src; + final Path src; final long lastModified; final String contentType; final String etag; final byte[] raw; - Resource(File src, long lastModified, String contentType, byte[] raw) { + Resource(Path src, long lastModified, String contentType, byte[] raw) { this.src = src; this.lastModified = lastModified; this.contentType = contentType; @@ -254,7 +249,7 @@ } boolean isStale() { - return lastModified != src.lastModified(); + return lastModified != lastModified(src); } } }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java index 321f032..9c067de 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/template/SiteHeaderFooter.java
@@ -14,6 +14,8 @@ package com.google.gerrit.httpd.template; +import static com.google.gerrit.common.FileUtil.lastModified; + import com.google.common.base.Strings; import com.google.gerrit.httpd.HtmlDomUtil; import com.google.gerrit.server.config.GerritServerConfig; @@ -27,8 +29,8 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; @Singleton public class SiteHeaderFooter { @@ -43,13 +45,13 @@ this.refreshHeaderFooter = cfg.getBoolean("site", "refreshHeaderFooter", true); this.sitePaths = sitePaths; - Template t = new Template(sitePaths); try { + Template t = new Template(sitePaths); t.load(); + template = t; } catch (IOException e) { log.warn("Cannot load site header or footer", e); } - template = t; } public Document parse(Class<?> clazz, String name) throws IOException { @@ -118,8 +120,8 @@ void load() throws IOException { css = HtmlDomUtil.readFile( - cssFile.path.getParentFile(), - cssFile.path.getName()); + cssFile.path.getParent(), + cssFile.path.getFileName().toString()); header = readXml(headerFile); footer = readXml(footerFile); } @@ -135,16 +137,16 @@ } private static class FileInfo { - final File path; + final Path path; final long time; - FileInfo(File p) { + FileInfo(Path p) { path = p; - time = path.lastModified(); + time = lastModified(p); } boolean isStale() { - return time != path.lastModified(); + return time != lastModified(path); } } }
diff --git a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java index e8825c5..0084536 100644 --- a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java +++ b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneChangeIndex.java
@@ -89,8 +89,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.sql.Timestamp; import java.util.Collections; import java.util.Iterator; @@ -223,7 +224,6 @@ private final ListeningExecutorService executor; private final Provider<ReviewDb> db; private final ChangeData.Factory changeDataFactory; - private final File dir; private final Schema<ChangeData> schema; private final QueryBuilder queryBuilder; private final SubIndex openIndex; @@ -246,11 +246,6 @@ this.changeDataFactory = changeDataFactory; this.schema = schema; - if (base == null) { - dir = LuceneVersionManager.getDir(sitePaths, schema); - } else { - dir = new File(base); - } Version luceneVersion = checkNotNull( LUCENE_VERSIONS.get(schema), "unknown Lucene version for index schema: %s", schema); @@ -271,8 +266,10 @@ openIndex = new SubIndex(new RAMDirectory(), "ramOpen", openConfig); closedIndex = new SubIndex(new RAMDirectory(), "ramClosed", closedConfig); } else { - openIndex = new SubIndex(new File(dir, CHANGES_OPEN), openConfig); - closedIndex = new SubIndex(new File(dir, CHANGES_CLOSED), closedConfig); + Path dir = base != null ? Paths.get(base) + : LuceneVersionManager.getDir(sitePaths, schema); + openIndex = new SubIndex(dir.resolve(CHANGES_OPEN), openConfig); + closedIndex = new SubIndex(dir.resolve(CHANGES_CLOSED), closedConfig); } }
diff --git a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneVersionManager.java b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneVersionManager.java index c3570a1..3c38225 100644 --- a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneVersionManager.java +++ b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/LuceneVersionManager.java
@@ -36,8 +36,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collection; import java.util.List; import java.util.TreeMap; @@ -65,15 +67,16 @@ } } - static File getDir(SitePaths sitePaths, Schema<ChangeData> schema) { - return new File(sitePaths.index_dir, String.format("%s%04d", + static Path getDir(SitePaths sitePaths, Schema<ChangeData> schema) { + return sitePaths.index_dir.resolve(String.format("%s%04d", CHANGES_PREFIX, schema.getVersion())); } static FileBasedConfig loadGerritIndexConfig(SitePaths sitePaths) throws ConfigInvalidException, IOException { FileBasedConfig cfg = new FileBasedConfig( - new File(sitePaths.index_dir, "gerrit_index.config"), FS.detect()); + sitePaths.index_dir.resolve("gerrit_index.config").toFile(), + FS.detect()); cfg.load(); return cfg; } @@ -114,10 +117,10 @@ throw fail(e); } - if (!sitePaths.index_dir.exists()) { + if (!Files.exists(sitePaths.index_dir)) { throw new ProvisionException("No index versions ready; run Reindex"); - } else if (!sitePaths.index_dir.isDirectory()) { - log.warn("Not a directory: %s", sitePaths.index_dir.getAbsolutePath()); + } else if (!Files.exists(sitePaths.index_dir)) { + log.warn("Not a directory: %s", sitePaths.index_dir.toAbsolutePath()); throw new ProvisionException("No index versions ready; run Reindex"); } @@ -167,29 +170,35 @@ private TreeMap<Integer, Version> scanVersions(Config cfg) { TreeMap<Integer, Version> versions = Maps.newTreeMap(); for (Schema<ChangeData> schema : ChangeSchemas.ALL.values()) { - File f = getDir(sitePaths, schema); - boolean exists = f.exists() && f.isDirectory(); - if (f.exists() && !f.isDirectory()) { - log.warn("Not a directory: %s", f.getAbsolutePath()); + Path p = getDir(sitePaths, schema); + boolean isDir = Files.isDirectory(p); + if (Files.exists(p) && !isDir) { + log.warn("Not a directory: %s", p.toAbsolutePath()); } int v = schema.getVersion(); - versions.put(v, new Version(schema, v, exists, getReady(cfg, v))); + versions.put(v, new Version(schema, v, isDir, getReady(cfg, v))); } - for (File f : sitePaths.index_dir.listFiles()) { - if (!f.getName().startsWith(CHANGES_PREFIX)) { - continue; + try (DirectoryStream<Path> paths = + Files.newDirectoryStream(sitePaths.index_dir)) { + for (Path p : paths) { + String n = p.getFileName().toString(); + if (!n.startsWith(CHANGES_PREFIX)) { + continue; + } + String versionStr = n.substring(CHANGES_PREFIX.length()); + Integer v = Ints.tryParse(versionStr); + if (v == null || versionStr.length() != 4) { + log.warn("Unrecognized version in index directory: {}", + p.toAbsolutePath()); + continue; + } + if (!versions.containsKey(v)) { + versions.put(v, new Version(null, v, true, getReady(cfg, v))); + } } - String versionStr = f.getName().substring(CHANGES_PREFIX.length()); - Integer v = Ints.tryParse(versionStr); - if (v == null || versionStr.length() != 4) { - log.warn("Unrecognized version in index directory: {}", - f.getAbsolutePath()); - continue; - } - if (!versions.containsKey(v)) { - versions.put(v, new Version(null, v, true, getReady(cfg, v))); - } + } catch (IOException e) { + log.error("Error scanning index directory: " + sitePaths.index_dir, e); } return versions; }
diff --git a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/SubIndex.java b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/SubIndex.java index e024f76..f28bf05 100644 --- a/gerrit-lucene/src/main/java/com/google/gerrit/lucene/SubIndex.java +++ b/gerrit-lucene/src/main/java/com/google/gerrit/lucene/SubIndex.java
@@ -37,8 +37,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -56,8 +56,9 @@ private final ControlledRealTimeReopenThread<IndexSearcher> reopenThread; private final Set<NrtFuture> notDoneNrtFutures; - SubIndex(File file, GerritIndexWriterConfig writerConfig) throws IOException { - this(FSDirectory.open(file), file.getName(), writerConfig); + SubIndex(Path path, GerritIndexWriterConfig writerConfig) throws IOException { + this(FSDirectory.open(path.toFile()), path.getFileName().toString(), + writerConfig); } SubIndex(Directory dir, final String dirName,
diff --git a/gerrit-pgm/BUCK b/gerrit-pgm/BUCK index 4b34629..7472ab3 100644 --- a/gerrit-pgm/BUCK +++ b/gerrit-pgm/BUCK
@@ -124,7 +124,9 @@ ':init', ':init-api', ':pgm', + '//gerrit-common:server', '//gerrit-server:server', + '//lib:guava', '//lib:junit', '//lib/easymock:easymock', '//lib/guice:guice',
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java index 7709b24..3f7d653 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
@@ -15,6 +15,7 @@ package com.google.gerrit.pgm; import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER; +import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; @@ -92,10 +93,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.lang.Thread.UncaughtExceptionHandler; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -147,7 +148,7 @@ private Injector sshInjector; private Injector webInjector; private Injector httpdInjector; - private File runFile; + private Path runFile; private boolean test; private AbstractModule luceneModule; @@ -183,7 +184,7 @@ }); if (runId != null) { - runFile = new File(new File(getSitePath(), "logs"), "gerrit.run"); + runFile = getSitePath().resolve("logs").resolve("gerrit.run"); } if (httpd == null) { @@ -207,7 +208,11 @@ public void run() { log.info("caught shutdown, cleaning up"); if (runId != null) { - runFile.delete(); + try { + Files.delete(runFile); + } catch (IOException err) { + log.warn("failed to delete " + runFile, err); + } } manager.stop(); } @@ -216,15 +221,8 @@ log.info("Gerrit Code Review " + myVersion() + " ready"); if (runId != null) { try { - runFile.createNewFile(); - runFile.setReadable(true, false); - - FileOutputStream out = new FileOutputStream(runFile); - try { - out.write((runId + "\n").getBytes("UTF-8")); - } finally { - out.close(); - } + Files.write(runFile, (runId + "\n").getBytes(UTF_8)); + runFile.toFile().setReadable(true, false); } catch (IOException err) { log.warn("Cannot write --run-id to " + runFile, err); }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java index 29ab490..efc97f9 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java
@@ -37,8 +37,8 @@ import org.kohsuke.args4j.Option; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -70,7 +70,7 @@ super(new WarDistribution(), null); } - public Init(File sitePath) { + public Init(Path sitePath) { super(sitePath, true, true, new WarDistribution(), null); batchMode = true; noAutoStart = true; @@ -106,7 +106,7 @@ modules.add(new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toInstance(getSitePath()); + bind(Path.class).annotatedWith(SitePath.class).toInstance(getSitePath()); bind(Browser.class); bind(String.class).annotatedWith(SecureStoreClassName.class) .toProvider(Providers.of(getConfiguredSecureStoreClass())); @@ -157,8 +157,8 @@ } void startDaemon(SiteRun run) { - final String[] argv = {run.site.gerrit_sh.getAbsolutePath(), "start"}; - final Process proc; + String[] argv = {run.site.gerrit_sh.toAbsolutePath().toString(), "start"}; + Process proc; try { System.err.println("Executing " + argv[0] + " " + argv[1]); proc = Runtime.getRuntime().exec(argv); @@ -177,7 +177,7 @@ for (;;) { try { - final int rc = proc.waitFor(); + int rc = proc.waitFor(); if (rc != 0) { System.err.println("error: cannot start Gerrit: exit status " + rc); }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/RebuildNotedb.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/RebuildNotedb.java index 88115b6..ab20f53 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/RebuildNotedb.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/RebuildNotedb.java
@@ -185,11 +185,8 @@ private static void execute(BatchRefUpdate bru, Repository repo) throws IOException { - RevWalk rw = new RevWalk(repo); - try { + try (RevWalk rw = new RevWalk(repo)) { bru.execute(rw, NullProgressMonitor.INSTANCE); - } finally { - rw.release(); } }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SwitchSecureStore.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SwitchSecureStore.java index f2feae1..ac84e82 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SwitchSecureStore.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/SwitchSecureStore.java
@@ -19,7 +19,6 @@ import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.Iterables; -import com.google.common.io.Files; import com.google.gerrit.common.IoUtil; import com.google.gerrit.common.SiteLibraryLoaderUtil; import com.google.gerrit.pgm.util.SiteProgram; @@ -37,8 +36,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import java.util.jar.JarFile; @@ -47,7 +48,7 @@ public class SwitchSecureStore extends SiteProgram { private static String getSecureStoreClassFromGerritConfig(SitePaths sitePaths) { FileBasedConfig cfg = - new FileBasedConfig(sitePaths.gerrit_config, FS.DETECTED); + new FileBasedConfig(sitePaths.gerrit_config.toFile(), FS.DETECTED); try { cfg.load(); } catch (IOException | ConfigInvalidException e) { @@ -67,14 +68,14 @@ @Override public int run() throws Exception { SitePaths sitePaths = new SitePaths(getSitePath()); - File newSecureStoreFile = new File(newSecureStoreLib); - if (!newSecureStoreFile.exists()) { - log.error(String.format("File %s doesn't exists", - newSecureStoreFile.getAbsolutePath())); + Path newSecureStorePath = Paths.get(newSecureStoreLib); + if (!Files.exists(newSecureStorePath)) { + log.error(String.format("File %s doesn't exist", + newSecureStorePath.toAbsolutePath())); return -1; } - String newSecureStore = getNewSecureStoreClassName(newSecureStoreFile); + String newSecureStore = getNewSecureStoreClassName(newSecureStorePath); String currentSecureStoreName = getCurrentSecureStoreClassName(sitePaths); if (currentSecureStoreName.equals(newSecureStore)) { @@ -83,7 +84,7 @@ return -1; } - IoUtil.loadJARs(newSecureStoreFile); + IoUtil.loadJARs(newSecureStorePath); SiteLibraryLoaderUtil.loadSiteLib(sitePaths.lib_dir); log.info("Current secureStoreClass property ({}) will be replaced with {}", @@ -96,7 +97,7 @@ migrateProperties(currentStore, newStore); removeOldLib(sitePaths, currentSecureStoreName); - copyNewLib(sitePaths, newSecureStoreFile); + copyNewLib(sitePaths, newSecureStorePath); updateGerritConfig(sitePaths, newSecureStore); @@ -123,14 +124,17 @@ } } - private void removeOldLib(SitePaths sitePaths, String currentSecureStoreName) { - File oldSecureStore = + private void removeOldLib(SitePaths sitePaths, String currentSecureStoreName) + throws IOException { + Path oldSecureStore = findJarWithSecureStore(sitePaths, currentSecureStoreName); if (oldSecureStore != null) { log.info("Removing old SecureStore ({}) from lib/ directory", - oldSecureStore.getName()); - if (!oldSecureStore.delete()) { - log.error("Cannot remove {}", oldSecureStore.getAbsolutePath()); + oldSecureStore.getFileName()); + try { + Files.delete(oldSecureStore); + } catch (IOException e) { + log.error("Cannot remove {}", oldSecureStore.toAbsolutePath(), e); } } else { log.info("Cannot find jar with old SecureStore ({}) in lib/ directory", @@ -138,12 +142,12 @@ } } - private void copyNewLib(SitePaths sitePaths, File newSecureStoreFile) + private void copyNewLib(SitePaths sitePaths, Path newSecureStorePath) throws IOException { log.info("Copy new SecureStore ({}) into lib/ directory", - newSecureStoreFile.getName()); - Files.copy(newSecureStoreFile, new File(sitePaths.lib_dir, - newSecureStoreFile.getName())); + newSecureStorePath.getFileName()); + Files.copy(newSecureStorePath, + sitePaths.lib_dir.resolve(newSecureStorePath.getFileName())); } private void updateGerritConfig(SitePaths sitePaths, String newSecureStore) @@ -151,13 +155,13 @@ log.info("Set gerrit.secureStoreClass property of gerrit.config to {}", newSecureStore); FileBasedConfig config = - new FileBasedConfig(sitePaths.gerrit_config, FS.DETECTED); + new FileBasedConfig(sitePaths.gerrit_config.toFile(), FS.DETECTED); config.load(); config.setString("gerrit", null, "secureStoreClass", newSecureStore); config.save(); } - private String getNewSecureStoreClassName(File secureStore) + private String getNewSecureStoreClassName(Path secureStore) throws IOException { JarScanner scanner = new JarScanner(secureStore); List<String> newSecureStores = @@ -165,12 +169,12 @@ if (newSecureStores.isEmpty()) { throw new RuntimeException(String.format( "Cannot find implementation of SecureStore interface in %s", - secureStore.getAbsolutePath())); + secureStore.toAbsolutePath())); } if (newSecureStores.size() > 1) { throw new RuntimeException(String.format( "Found too many implementations of SecureStore:\n%s\nin %s", Joiner - .on("\n").join(newSecureStores), secureStore.getAbsolutePath())); + .on("\n").join(newSecureStores), secureStore.toAbsolutePath())); } return Iterables.getOnlyElement(newSecureStores); } @@ -195,15 +199,12 @@ } } - private File findJarWithSecureStore(SitePaths sitePaths, - String secureStoreClass) { - File[] jars = SiteLibraryLoaderUtil.listJars(sitePaths.lib_dir); - if (jars == null || jars.length == 0) { - return null; - } + private Path findJarWithSecureStore(SitePaths sitePaths, + String secureStoreClass) throws IOException { + List<Path> jars = SiteLibraryLoaderUtil.listJars(sitePaths.lib_dir); String secureStoreClassPath = secureStoreClass.replace('.', '/') + ".class"; - for (File jar : jars) { - try (JarFile jarFile = new JarFile(jar)) { + for (Path jar : jars) { + try (JarFile jarFile = new JarFile(jar.toFile())) { ZipEntry entry = jarFile.getEntry(secureStoreClassPath); if (entry != null) { return jar;
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java index 907624d..0497b71 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
@@ -81,6 +81,8 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.EnumSet; import java.util.Enumeration; @@ -220,22 +222,22 @@ } else if ("https".equals(u.getScheme())) { SslContextFactory ssl = new SslContextFactory(); - final File keystore = getFile(cfg, "sslkeystore", "etc/keystore"); + final Path keystore = getFile(cfg, "sslkeystore", "etc/keystore"); String password = cfg.getString("httpd", null, "sslkeypassword"); if (password == null) { password = "gerrit"; } - ssl.setKeyStorePath(keystore.getAbsolutePath()); - ssl.setTrustStorePath(keystore.getAbsolutePath()); + ssl.setKeyStorePath(keystore.toAbsolutePath().toString()); + ssl.setTrustStorePath(keystore.toAbsolutePath().toString()); ssl.setKeyStorePassword(password); ssl.setTrustStorePassword(password); if (AuthType.CLIENT_SSL_CERT_LDAP.equals(authType)) { ssl.setNeedClientAuth(true); - File crl = getFile(cfg, "sslcrl", "etc/crl.pem"); - if (crl.exists()) { - ssl.setCrlPath(crl.getAbsolutePath()); + Path crl = getFile(cfg, "sslcrl", "etc/crl.pem"); + if (Files.exists(crl)) { + ssl.setCrlPath(crl.toAbsolutePath().toString()); ssl.setValidatePeerCerts(true); } } @@ -340,7 +342,7 @@ return r; } - private File getFile(final Config cfg, final String name, final String def) { + private Path getFile(Config cfg, String name, String def) { String path = cfg.getString("httpd", null, name); if (path == null || path.length() == 0) { path = def;
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/BaseInit.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/BaseInit.java index c9e76c8..534ef050 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/BaseInit.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/BaseInit.java
@@ -56,9 +56,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -86,12 +91,12 @@ this.pluginsToInstall = pluginsToInstall; } - public BaseInit(File sitePath, boolean standalone, boolean initDb, + public BaseInit(Path sitePath, boolean standalone, boolean initDb, PluginsDistribution pluginsDistribution, List<String> pluginsToInstall) { this(sitePath, null, standalone, initDb, pluginsDistribution, pluginsToInstall); } - public BaseInit(File sitePath, final Provider<DataSource> dsProvider, + public BaseInit(Path sitePath, final Provider<DataSource> dsProvider, boolean standalone, boolean initDb, PluginsDistribution pluginsDistribution, List<String> pluginsToInstall) { super(sitePath, dsProvider); @@ -132,7 +137,7 @@ throw failure; } - System.err.println("Initialized " + getSitePath().getCanonicalPath()); + System.err.println("Initialized " + getSitePath().toRealPath().normalize()); afterInit(run); return 0; } @@ -208,7 +213,7 @@ private SiteInit createSiteInit() { final ConsoleUI ui = getConsoleUI(); - final File sitePath = getSitePath(); + final Path sitePath = getSitePath(); final List<Module> m = new ArrayList<>(); final SecureStoreInitData secureStoreInitData = discoverSecureStoreClass(); final String currentSecureStoreClassName = getConfiguredSecureStoreClass(); @@ -228,7 +233,7 @@ @Override protected void configure() { bind(ConsoleUI.class).toInstance(ui); - bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath); + bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath); List<String> plugins = MoreObjects.firstNonNull( getInstallPlugins(), Lists.<String> newArrayList()); @@ -287,8 +292,8 @@ } try { - File secureStoreLib = new File(secureStore); - if (!secureStoreLib.exists()) { + Path secureStoreLib = Paths.get(secureStore); + if (!Files.exists(secureStoreLib)) { throw new InvalidSecureStoreException(String.format( "File %s doesn't exist", secureStore)); } @@ -408,15 +413,41 @@ return sysInjector; } - private static void recursiveDelete(File path) { - File[] entries = path.listFiles(); - if (entries != null) { - for (File e : entries) { - recursiveDelete(e); - } - } - if (!path.delete() && path.exists()) { - System.err.println("warn: Cannot remove " + path); + private static void recursiveDelete(Path path) { + final String msg = "warn: Cannot remove "; + try { + Files.walkFileTree(path, new SimpleFileVisitor<Path>() { + @Override + public FileVisitResult visitFile(Path f, BasicFileAttributes attrs) + throws IOException { + try { + Files.delete(f); + } catch (IOException e) { + System.err.println(msg + f); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException err) { + try { + // Previously warned if err was not null; if dir is not empty as a + // result, will cause an error that will be logged below. + Files.delete(dir); + } catch (IOException e) { + System.err.println(msg + dir); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path f, IOException e) { + System.err.println(msg + f); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + System.err.println(msg + path); } } }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/H2Initializer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/H2Initializer.java index e20346a..6d60ad1 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/H2Initializer.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/H2Initializer.java
@@ -14,12 +14,14 @@ package com.google.gerrit.pgm.init; -import com.google.gerrit.pgm.init.api.InitUtil; +import static com.google.gerrit.pgm.init.api.InitUtil.die; + +import com.google.gerrit.common.FileUtil; import com.google.gerrit.pgm.init.api.Section; import com.google.gerrit.server.config.SitePaths; import com.google.inject.Inject; -import java.io.File; +import java.nio.file.Path; class H2Initializer implements DatabaseConfigInitializer { @@ -33,18 +35,17 @@ @Override public void initConfig(Section databaseSection) { String path = databaseSection.get("database"); + Path db; if (path == null) { - path = "db/ReviewDB"; - databaseSection.set("database", path); + db = site.resolve("db").resolve("ReviewDB"); + databaseSection.set("database", db.toString()); + } else { + db = site.resolve(path); } - File db = site.resolve(path); if (db == null) { - throw InitUtil.die("database.database must be supplied for H2"); + throw die("database.database must be supplied for H2"); } - db = db.getParentFile(); - if (!db.exists() && !db.mkdirs()) { - throw InitUtil.die("cannot create database.database " - + db.getAbsolutePath()); - } + db = db.getParent(); + FileUtil.mkdirsOrDie(db, "cannot create database.database"); } -} \ No newline at end of file +}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitCache.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitCache.java index 8da4a03..4e5d044 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitCache.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitCache.java
@@ -14,15 +14,14 @@ package com.google.gerrit.pgm.init; -import static com.google.gerrit.pgm.init.api.InitUtil.die; - +import com.google.gerrit.common.FileUtil; import com.google.gerrit.pgm.init.api.InitStep; import com.google.gerrit.pgm.init.api.Section; import com.google.gerrit.server.config.SitePaths; import com.google.inject.Inject; import com.google.inject.Singleton; -import java.io.File; +import java.nio.file.Path; /** Initialize the {@code cache} configuration section. */ @Singleton @@ -52,10 +51,8 @@ cache.set("directory", path); } - final File loc = site.resolve(path); - if (!loc.exists() && !loc.mkdirs()) { - throw die("cannot create cache.directory " + loc.getAbsolutePath()); - } + Path loc = site.resolve(path); + FileUtil.mkdirsOrDie(loc, "cannot create cache.directory"); } @Override
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitContainer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitContainer.java index f830854..60ff665 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitContainer.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitContainer.java
@@ -17,6 +17,7 @@ import static com.google.gerrit.pgm.init.api.InitUtil.die; import static com.google.gerrit.pgm.init.api.InitUtil.username; +import com.google.common.io.ByteStreams; import com.google.gerrit.launcher.GerritLauncher; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.pgm.init.api.InitStep; @@ -28,11 +29,12 @@ import org.eclipse.jgit.internal.storage.file.LockFile; import org.eclipse.jgit.util.FS; -import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; /** Initialize the {@code container} configuration section. */ @Singleton @@ -56,9 +58,9 @@ container.string("Run as", "user", username()); container.string("Java runtime", "javaHome", javaHome()); - File myWar; + Path myWar; try { - myWar = GerritLauncher.getDistributionArchive(); + myWar = GerritLauncher.getDistributionArchive().toPath(); } catch (FileNotFoundException e) { System.err.println("warn: Cannot find distribution archive (e.g. gerrit.war)"); myWar = null; @@ -66,53 +68,41 @@ String path = container.get("war"); if (path != null) { - path = container.string("Gerrit runtime", "war", // - myWar != null ? myWar.getAbsolutePath() : null); + path = container.string("Gerrit runtime", "war", + myWar != null ? myWar.toAbsolutePath().toString() : null); if (path == null || path.isEmpty()) { throw die("container.war is required"); } } else if (myWar != null) { final boolean copy; - final File siteWar = site.gerrit_war; - if (siteWar.exists()) { - copy = ui.yesno(true, "Upgrade %s", siteWar.getPath()); + final Path siteWar = site.gerrit_war; + if (Files.exists(siteWar)) { + copy = ui.yesno(true, "Upgrade %s", siteWar); } else { - copy = ui.yesno(true, "Copy %s to %s", myWar.getName(), siteWar.getPath()); + copy = ui.yesno(true, "Copy %s to %s", myWar.getFileName(), siteWar); if (copy) { container.unset("war"); } else { - container.set("war", myWar.getAbsolutePath()); + container.set("war", myWar.toAbsolutePath().toString()); } } if (copy) { if (!ui.isBatch()) { - System.err.format("Copying %s to %s", myWar.getName(), siteWar.getPath()); + System.err.format("Copying %s to %s", myWar.getFileName(), siteWar); System.err.println(); } - FileInputStream in = new FileInputStream(myWar); - try { - siteWar.getParentFile().mkdirs(); + try (InputStream in = Files.newInputStream(myWar)) { + Files.createDirectories(siteWar.getParent()); - LockFile lf = new LockFile(siteWar, FS.DETECTED); + LockFile lf = new LockFile(siteWar.toFile(), FS.DETECTED); if (!lf.lock()) { throw new IOException("Cannot lock " + siteWar); } - try { - final OutputStream out = lf.getOutputStream(); - try { - final byte[] tmp = new byte[4096]; - for (;;) { - int n = in.read(tmp); - if (n < 0) { - break; - } - out.write(tmp, 0, n); - } - } finally { - out.close(); + try (OutputStream out = lf.getOutputStream()) { + ByteStreams.copy(in, out); } if (!lf.commit()) { throw new IOException("Cannot commit " + siteWar); @@ -120,8 +110,6 @@ } finally { lf.unlock(); } - } finally { - in.close(); } } }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitGitManager.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitGitManager.java index 067b103..d8fd509 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitGitManager.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitGitManager.java
@@ -16,13 +16,14 @@ import static com.google.gerrit.pgm.init.api.InitUtil.die; +import com.google.gerrit.common.FileUtil; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.pgm.init.api.InitStep; import com.google.gerrit.pgm.init.api.Section; import com.google.inject.Inject; import com.google.inject.Singleton; -import java.io.File; +import java.nio.file.Path; /** Initialize the GitRepositoryManager configuration section. */ @Singleton @@ -40,13 +41,11 @@ public void run() { ui.header("Git Repositories"); - File d = gerrit.path("Location of Git repositories", "basePath", "git"); + Path d = gerrit.path("Location of Git repositories", "basePath", "git"); if (d == null) { throw die("gerrit.basePath is required"); } - if (!d.exists() && !d.mkdirs()) { - throw die("Cannot create " + d); - } + FileUtil.mkdirsOrDie(d, "Cannot create"); } @Override
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java index c8f1cd7..bf373ea 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java
@@ -29,10 +29,11 @@ import com.google.inject.Inject; import com.google.inject.Singleton; -import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; /** Initialize the {@code httpd} configuration section. */ @Singleton @@ -149,8 +150,9 @@ return; } - final File store = site.ssl_keystore; - if (!ui.yesno(!store.exists(), "Create new self-signed SSL certificate")) { + Path store = site.ssl_keystore; + if (!ui.yesno(!Files.exists(store), + "Create new self-signed SSL certificate")) { return; } @@ -167,15 +169,17 @@ final String dname = "CN=" + hostname + ",OU=Gerrit Code Review,O=" + domainOf(hostname); - final File tmpdir = new File(site.etc_dir, "tmp.sslcertgen"); - if (!tmpdir.mkdir()) { - throw die("Cannot create directory " + tmpdir); + Path tmpdir = site.etc_dir.resolve("tmp.sslcertgen"); + try { + Files.createDirectory(tmpdir); + } catch (IOException e) { + throw die("Cannot create directory " + tmpdir, e); } chmod(0600, tmpdir); - final File tmpstore = new File(tmpdir, "keystore"); + Path tmpstore = tmpdir.resolve("keystore"); Runtime.getRuntime().exec(new String[] {"keytool", // - "-keystore", tmpstore.getAbsolutePath(), // + "-keystore", tmpstore.toAbsolutePath().toString(), // "-storepass", ssl_pass, // "-genkeypair", // "-alias", hostname, // @@ -186,11 +190,15 @@ }).waitFor(); chmod(0600, tmpstore); - if (!tmpstore.renameTo(store)) { - throw die("Cannot rename " + tmpstore + " to " + store); + try { + Files.move(tmpstore, store); + } catch (IOException e) { + throw die("Cannot rename " + tmpstore + " to " + store, e); } - if (!tmpdir.delete()) { - throw die("Cannot delete " + tmpdir); + try { + Files.delete(tmpdir); + } catch (IOException e) { + throw die("Cannot delete " + tmpdir, e); } }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPluginStepsLoader.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPluginStepsLoader.java index 893f00d..2cffe42 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPluginStepsLoader.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPluginStepsLoader.java
@@ -15,6 +15,7 @@ package com.google.gerrit.pgm.init; import com.google.common.base.MoreObjects; +import com.google.common.collect.Ordering; import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.pgm.init.api.InitStep; @@ -26,23 +27,22 @@ import com.google.inject.Injector; import com.google.inject.Singleton; -import java.io.File; -import java.io.FileFilter; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.List; import java.util.jar.Attributes; import java.util.jar.JarFile; @Singleton public class InitPluginStepsLoader { - private final File pluginsDir; + private final Path pluginsDir; private final Injector initInjector; final ConsoleUI ui; @@ -55,10 +55,10 @@ } public Collection<InitStep> getInitSteps() { - List<File> jars = scanJarsInPluginsDirectory(); + List<Path> jars = scanJarsInPluginsDirectory(); ArrayList<InitStep> pluginsInitSteps = new ArrayList<>(); - for (File jar : jars) { + for (Path jar : jars) { InitStep init = loadInitStep(jar); if (init != null) { pluginsInitSteps.add(init); @@ -68,12 +68,12 @@ } @SuppressWarnings("resource") - private InitStep loadInitStep(File jar) { + private InitStep loadInitStep(Path jar) { try { URLClassLoader pluginLoader = - new URLClassLoader(new URL[] {jar.toURI().toURL()}, + new URLClassLoader(new URL[] {jar.toUri().toURL()}, InitPluginStepsLoader.class.getClassLoader()); - try (JarFile jarFile = new JarFile(jar)) { + try (JarFile jarFile = new JarFile(jar.toFile())) { Attributes jarFileAttributes = jarFile.getManifest().getMainAttributes(); String initClassName = jarFileAttributes.getValue("Gerrit-InitStep"); if (initClassName == null) { @@ -86,7 +86,7 @@ } catch (ClassCastException e) { ui.message( "WARN: InitStep from plugin %s does not implement %s (Exception: %s)", - jar.getName(), InitStep.class.getName(), e.getMessage()); + jar.getFileName(), InitStep.class.getName(), e.getMessage()); return null; } } catch (Exception e) { @@ -97,11 +97,10 @@ } } - private Injector getPluginInjector(final File jarFile) throws IOException { - final String pluginName = - MoreObjects.firstNonNull( - JarPluginProvider.getJarPluginName(jarFile), - PluginLoader.nameOf(jarFile)); + private Injector getPluginInjector(Path jarPath) throws IOException { + final String pluginName = MoreObjects.firstNonNull( + JarPluginProvider.getJarPluginName(jarPath), + PluginLoader.nameOf(jarPath)); return initInjector.createChildInjector(new AbstractModule() { @Override protected void configure() { @@ -111,27 +110,24 @@ }); } - private List<File> scanJarsInPluginsDirectory() { - if (pluginsDir == null || !pluginsDir.exists()) { + private List<Path> scanJarsInPluginsDirectory() { + if (pluginsDir == null || !Files.isDirectory(pluginsDir)) { return Collections.emptyList(); } - File[] matches = pluginsDir.listFiles(new FileFilter() { + DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() { @Override - public boolean accept(File pathname) { - String n = pathname.getName(); - return (n.endsWith(".jar") && pathname.isFile()); + public boolean accept(Path entry) throws IOException { + return entry.getFileName().toString().endsWith(".jar") + && Files.isRegularFile(entry); } - }); - if (matches == null) { - ui.message("WARN: Cannot list %s", pluginsDir.getAbsolutePath()); + }; + try (DirectoryStream<Path> paths = + Files.newDirectoryStream(pluginsDir, filter)) { + return Ordering.natural().sortedCopy(paths); + } catch (IOException e) { + ui.message("WARN: Cannot list %s: %s", pluginsDir.toAbsolutePath(), + e.getMessage()); return Collections.emptyList(); } - Arrays.sort(matches, new Comparator<File>() { - @Override - public int compare(File o1, File o2) { - return o1.getName().compareTo(o2.getName()); - } - }); - return Arrays.asList(matches); } }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPlugins.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPlugins.java index cc076b5..ca4b949 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPlugins.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitPlugins.java
@@ -25,9 +25,10 @@ import com.google.inject.Injector; import com.google.inject.Singleton; -import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; import java.util.jar.Attributes; import java.util.jar.JarFile; @@ -55,10 +56,10 @@ pluginsDistribution.foreach(new PluginsDistribution.Processor() { @Override public void process(String pluginName, InputStream in) throws IOException { - File tmpPlugin = JarPluginProvider.storeInTemp(pluginName, in, site); + Path tmpPlugin = JarPluginProvider.storeInTemp(pluginName, in, site); String pluginVersion = getVersion(tmpPlugin); if (deleteTempPluginFile) { - tmpPlugin.delete(); + Files.delete(tmpPlugin); } result.add(new PluginData(pluginName, pluginVersion, tmpPlugin)); } @@ -108,37 +109,39 @@ for (PluginData plugin : plugins) { String pluginName = plugin.name; try { - final File tmpPlugin = plugin.pluginFile; + final Path tmpPlugin = plugin.pluginPath; if (!(initFlags.installPlugins.contains(pluginName) || ui.yesno(false, "Install plugin %s version %s", pluginName, plugin.version))) { - tmpPlugin.delete(); + Files.deleteIfExists(tmpPlugin); continue; } - final File p = new File(site.plugins_dir, plugin.name + ".jar"); - if (p.exists()) { + final Path p = site.plugins_dir.resolve(plugin.name + ".jar"); + if (Files.exists(p)) { final String installedPluginVersion = getVersion(p); if (!ui.yesno(false, "version %s is already installed, overwrite it", installedPluginVersion)) { - tmpPlugin.delete(); + Files.deleteIfExists(tmpPlugin); continue; } - if (!p.delete()) { + try { + Files.delete(p); + } catch (IOException e) { throw new IOException("Failed to delete plugin " + pluginName - + ": " + p.getAbsolutePath()); + + ": " + p.toAbsolutePath(), e); } } - if (!tmpPlugin.renameTo(p)) { + try { + Files.move(tmpPlugin, p); + } catch (IOException e) { throw new IOException("Failed to install plugin " + pluginName - + ": " + tmpPlugin.getAbsolutePath() + " -> " - + p.getAbsolutePath()); + + ": " + tmpPlugin.toAbsolutePath() + " -> " + + p.toAbsolutePath(), e); } } finally { - if (plugin.pluginFile.exists()) { - plugin.pluginFile.delete(); - } + Files.deleteIfExists(plugin.pluginPath); } } if (plugins.isEmpty()) { @@ -159,11 +162,11 @@ } } - private static String getVersion(final File plugin) throws IOException { - final JarFile jarFile = new JarFile(plugin); + private static String getVersion(Path plugin) throws IOException { + JarFile jarFile = new JarFile(plugin.toFile()); try { - final Manifest manifest = jarFile.getManifest(); - final Attributes main = manifest.getMainAttributes(); + Manifest manifest = jarFile.getManifest(); + Attributes main = manifest.getMainAttributes(); return main.getValue(Attributes.Name.IMPLEMENTATION_VERSION); } finally { jarFile.close();
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSendEmail.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSendEmail.java index 51eaa22..5c7eefd 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSendEmail.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSendEmail.java
@@ -25,6 +25,8 @@ import com.google.inject.Inject; import com.google.inject.Singleton; +import java.nio.file.Files; + /** Initialize the {@code sendemail} configuration section. */ @Singleton class InitSendEmail implements InitStep { @@ -54,7 +56,7 @@ true); String username = null; - if (site.gerrit_config.exists()) { + if (Files.exists(site.gerrit_config)) { username = sendemail.get("smtpUser"); } else if ((enc != null && enc != Encryption.NONE) || !isLocal(hostname)) { username = username();
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java index ed18d73..c654c8d 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitSshd.java
@@ -17,6 +17,7 @@ import static com.google.gerrit.common.FileUtil.chmod; import static com.google.gerrit.pgm.init.api.InitUtil.die; import static com.google.gerrit.pgm.init.api.InitUtil.hostname; +import static java.nio.file.Files.exists; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.pgm.init.api.InitStep; @@ -29,9 +30,10 @@ import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; -import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Path; /** Initialize the {@code sshd} configuration section. */ @Singleton @@ -74,9 +76,9 @@ port = ui.readInt(port, "Listen on port"); sshd.set("listenAddress", SocketUtil.format(hostname, port)); - if (site.ssh_rsa.exists() || site.ssh_dsa.exists()) { + if (exists(site.ssh_rsa) || exists(site.ssh_dsa)) { libraries.bouncyCastleSSL.downloadRequired(); - } else if (!site.ssh_key.exists()) { + } else if (!exists(site.ssh_key)) { libraries.bouncyCastleSSL.downloadOptional(); } @@ -90,9 +92,9 @@ } private void generateSshHostKeys() throws InterruptedException, IOException { - if (!site.ssh_key.exists() // - && !site.ssh_rsa.exists() // - && !site.ssh_dsa.exists()) { + if (!exists(site.ssh_key) // + && !exists(site.ssh_rsa) // + && !exists(site.ssh_dsa)) { System.err.print("Generating SSH host key ..."); System.err.flush(); @@ -108,7 +110,7 @@ "-t", "rsa", // "-P", "", // "-C", comment, // - "-f", site.ssh_rsa.getAbsolutePath() // + "-f", site.ssh_rsa.toAbsolutePath().toString() // }).waitFor(); System.err.print(" dsa..."); @@ -118,7 +120,7 @@ "-t", "dsa", // "-P", "", // "-C", comment, // - "-f", site.ssh_dsa.getAbsolutePath() // + "-f", site.ssh_dsa.toAbsolutePath().toString() // }).waitFor(); } else { @@ -128,28 +130,34 @@ // short period of time. We try to reduce that risk by creating // the key within a temporary directory. // - final File tmpdir = new File(site.etc_dir, "tmp.sshkeygen"); - if (!tmpdir.mkdir()) { - throw die("Cannot create directory " + tmpdir); + Path tmpdir = site.etc_dir.resolve("tmp.sshkeygen"); + try { + Files.createDirectory(tmpdir); + } catch (IOException e) { + throw die("Cannot create directory " + tmpdir, e); } chmod(0600, tmpdir); - final File tmpkey = new File(tmpdir, site.ssh_key.getName()); - final SimpleGeneratorHostKeyProvider p; + Path tmpkey = tmpdir.resolve(site.ssh_key.getFileName().toString()); + SimpleGeneratorHostKeyProvider p; System.err.print(" rsa(simple)..."); System.err.flush(); p = new SimpleGeneratorHostKeyProvider(); - p.setPath(tmpkey.getAbsolutePath()); + p.setPath(tmpkey.toAbsolutePath().toString()); p.setAlgorithm("RSA"); p.loadKeys(); // forces the key to generate. chmod(0600, tmpkey); - if (!tmpkey.renameTo(site.ssh_key)) { - throw die("Cannot rename " + tmpkey + " to " + site.ssh_key); + try { + Files.move(tmpkey, site.ssh_key); + } catch (IOException e) { + throw die("Cannot rename " + tmpkey + " to " + site.ssh_key, e); } - if (!tmpdir.delete()) { - throw die("Cannot delete " + tmpdir); + try { + Files.delete(tmpdir); + } catch (IOException e) { + throw die("Cannot delete " + tmpdir, e); } } System.err.println(" done");
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/LibraryDownloader.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/LibraryDownloader.java index 4bf1c88..00c7c58 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/LibraryDownloader.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/LibraryDownloader.java
@@ -15,21 +15,19 @@ package com.google.gerrit.pgm.init; import com.google.common.base.Strings; -import com.google.common.io.Files; +import com.google.common.hash.Funnels; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; +import com.google.common.io.ByteStreams; import com.google.gerrit.common.Die; import com.google.gerrit.common.IoUtil; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.server.config.SitePaths; import com.google.inject.Inject; -import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.util.HttpSupport; -import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -38,15 +36,17 @@ import java.net.ProxySelector; import java.net.URISyntaxException; import java.net.URL; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; /** Get optional or required 3rd party library files into $site_path/lib. */ class LibraryDownloader { private final ConsoleUI ui; - private final File lib_dir; + private final Path lib_dir; private boolean required; private String name; @@ -55,7 +55,7 @@ private String remove; private List<LibraryDownloader> needs; private LibraryDownloader neededBy; - private File dst; + private Path dst; private boolean download; // download or copy private boolean exists; @@ -118,8 +118,8 @@ name = jarName; } - dst = new File(lib_dir, jarName); - if (dst.exists()) { + dst = lib_dir.resolve(jarName); + if (Files.exists(dst)) { exists = true; } else if (shouldGet()) { doGet(); @@ -158,8 +158,12 @@ } private void doGet() { - if (!lib_dir.exists() && !lib_dir.mkdirs()) { - throw new Die("Cannot create " + lib_dir); + if (!Files.exists(lib_dir)) { + try { + Files.createDirectories(lib_dir); + } catch (IOException e) { + throw new Die("Cannot create " + lib_dir, e); + } } try { @@ -171,7 +175,11 @@ } verifyFileChecksum(); } catch (IOException err) { - dst.delete(); + try { + Files.delete(dst); + } catch (IOException e) { + // Delete failed; leave alone. + } if (ui.isBatch()) { throw new Die("error: Cannot get " + jarUrl, err); @@ -186,13 +194,13 @@ System.err.println(); System.err.println("and save as:"); System.err.println(); - System.err.println(" " + dst.getAbsolutePath()); + System.err.println(" " + dst.toAbsolutePath()); System.err.println(); System.err.flush(); ui.waitForUser(); - if (dst.exists()) { + if (Files.exists(dst)) { verifyFileChecksum(); } else if (!ui.yesno(!required, "Continue without this library")) { @@ -200,7 +208,7 @@ } } - if (dst.exists()) { + if (Files.exists(dst)) { exists = true; IoUtil.loadJARs(dst); } @@ -208,131 +216,120 @@ private void removeStaleVersions() { if (!Strings.isNullOrEmpty(remove)) { - String[] names = lib_dir.list(new FilenameFilter() { + DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() { @Override - public boolean accept(File dir, String name) { - return name.matches("^" + remove + "$"); + public boolean accept(Path entry) { + return entry.getFileName().toString() + .matches("^" + remove + "$"); } - }); - if (names != null) { - for (String old : names) { + }; + try (DirectoryStream<Path> paths = + Files.newDirectoryStream(lib_dir, filter)) { + for (Path p : paths) { + String old = p.getFileName().toString(); String bak = "." + old + ".backup"; ui.message("Renaming %s to %s", old, bak); - if (!new File(lib_dir, old).renameTo(new File(lib_dir, bak))) { - throw new Die("cannot rename " + old); + try { + Files.move(p, p.resolveSibling(bak)); + } catch (IOException e) { + throw new Die("cannot rename " + old, e); } } + } catch (IOException e) { + throw new Die("cannot remove stale library versions", e); } } } private void doGetByLocalCopy() throws IOException { System.err.print("Copying " + jarUrl + " ..."); - File f = url2file(jarUrl); - if (!f.exists()) { + Path p = url2file(jarUrl); + if (!Files.exists(p)) { StringBuilder msg = new StringBuilder() .append("\n") .append("Can not find the %s at this location: %s\n") .append("Please provide alternative URL"); - f = url2file(ui.readString(null, msg.toString(), name, jarUrl)); + p = url2file(ui.readString(null, msg.toString(), name, jarUrl)); } - Files.copy(f, dst); + Files.copy(p, dst); } - private static File url2file(final String urlString) throws IOException { + private static Path url2file(final String urlString) throws IOException { final URL url = new URL(urlString); try { - return new File(url.toURI()); + return Paths.get(url.toURI()); } catch (URISyntaxException e) { - return new File(url.getPath()); + return Paths.get(url.getPath()); } } private void doGetByHttp() throws IOException { System.err.print("Downloading " + jarUrl + " ..."); System.err.flush(); - try { - final ProxySelector proxySelector = ProxySelector.getDefault(); - final URL url = new URL(jarUrl); - final Proxy proxy = HttpSupport.proxyFor(proxySelector, url); - final HttpURLConnection c = (HttpURLConnection) url.openConnection(proxy); - final InputStream in; - - switch (HttpSupport.response(c)) { - case HttpURLConnection.HTTP_OK: - in = c.getInputStream(); - break; - - case HttpURLConnection.HTTP_NOT_FOUND: - throw new FileNotFoundException(url.toString()); - - default: - throw new IOException(url.toString() + ": " + HttpSupport.response(c) - + " " + c.getResponseMessage()); - } - - try { - final OutputStream out = new FileOutputStream(dst); - try { - final byte[] buf = new byte[8192]; - int n; - while ((n = in.read(buf)) > 0) { - out.write(buf, 0, n); - } - } finally { - out.close(); - } - } finally { - in.close(); - } + try (InputStream in = openHttpStream(jarUrl); + OutputStream out = Files.newOutputStream(dst)) { + ByteStreams.copy(in, out); System.err.println(" OK"); System.err.flush(); } catch (IOException err) { - dst.delete(); + deleteDst(); System.err.println(" !! FAIL !!"); System.err.flush(); throw err; } } + private static InputStream openHttpStream(String urlStr) throws IOException { + ProxySelector proxySelector = ProxySelector.getDefault(); + URL url = new URL(urlStr); + Proxy proxy = HttpSupport.proxyFor(proxySelector, url); + HttpURLConnection c = (HttpURLConnection) url.openConnection(proxy); + + switch (HttpSupport.response(c)) { + case HttpURLConnection.HTTP_OK: + return c.getInputStream(); + + case HttpURLConnection.HTTP_NOT_FOUND: + throw new FileNotFoundException(url.toString()); + + default: + throw new IOException(url.toString() + ": " + HttpSupport.response(c) + + " " + c.getResponseMessage()); + } + } + private void verifyFileChecksum() { - if (sha1 != null) { - try { - final MessageDigest md = MessageDigest.getInstance("SHA-1"); - final FileInputStream in = new FileInputStream(dst); - try { - final byte[] buf = new byte[8192]; - int n; - while ((n = in.read(buf)) > 0) { - md.update(buf, 0, n); - } - } finally { - in.close(); - } + if (sha1 == null) { + return; + } + Hasher h = Hashing.sha1().newHasher(); + try (InputStream in = Files.newInputStream(dst); + OutputStream out = Funnels.asOutputStream(h)) { + ByteStreams.copy(in, out); + } catch (IOException e) { + deleteDst(); + throw new Die("cannot checksum " + dst, e); + } + if (sha1.equals(h.hash().toString())) { + System.err.println("Checksum " + dst.getFileName() + " OK"); + System.err.flush(); + } else if (ui.isBatch()) { + deleteDst(); + throw new Die(dst + " SHA-1 checksum does not match"); - if (sha1.equals(ObjectId.fromRaw(md.digest()).name())) { - System.err.println("Checksum " + dst.getName() + " OK"); - System.err.flush(); + } else if (!ui.yesno(null /* force an answer */, + "error: SHA-1 checksum does not match\n" + "Use %s anyway",// + dst.getFileName())) { + deleteDst(); + throw new Die("aborted by user"); + } + } - } else if (ui.isBatch()) { - dst.delete(); - throw new Die(dst + " SHA-1 checksum does not match"); - - } else if (!ui.yesno(null /* force an answer */, - "error: SHA-1 checksum does not match\n" + "Use %s anyway",// - dst.getName())) { - dst.delete(); - throw new Die("aborted by user"); - } - - } catch (IOException checksumError) { - dst.delete(); - throw new Die("cannot checksum " + dst, checksumError); - - } catch (NoSuchAlgorithmException checksumError) { - dst.delete(); - throw new Die("cannot checksum " + dst, checksumError); - } + private void deleteDst() { + try { + Files.delete(dst); + } catch (IOException e) { + System.err.println(" Failed to clean up lib: " + dst); } } }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SecureStoreInitData.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SecureStoreInitData.java index 8926759..49877dc 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SecureStoreInitData.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SecureStoreInitData.java
@@ -14,13 +14,13 @@ package com.google.gerrit.pgm.init; -import java.io.File; +import java.nio.file.Path; class SecureStoreInitData { - final File jarFile; + final Path jarFile; final String className; - SecureStoreInitData(File jar, String className) { + SecureStoreInitData(Path jar, String className) { this.className = className; this.jarFile = jar; }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java index 10c9bad..c30fe58 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java
@@ -21,7 +21,7 @@ import static com.google.gerrit.pgm.init.api.InitUtil.savePublic; import static com.google.gerrit.pgm.init.api.InitUtil.version; -import com.google.common.io.Files; +import com.google.gerrit.common.FileUtil; import com.google.gerrit.common.Nullable; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.pgm.init.api.InitFlags; @@ -35,8 +35,9 @@ import com.google.inject.Injector; import com.google.inject.TypeLiteral; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -66,12 +67,10 @@ ui.header("Gerrit Code Review %s", version()); if (site.isNew) { - if (!ui.yesno(true, "Create '%s'", site.site_path.getCanonicalPath())) { + if (!ui.yesno(true, "Create '%s'", site.site_path.toAbsolutePath())) { throw die("aborted by user"); } - if (!site.site_path.isDirectory() && !site.site_path.mkdirs()) { - throw die("Cannot make directory " + site.site_path); - } + FileUtil.mkdirsOrDie(site.site_path, "Cannot make directory"); flags.deleteOnFailure = true; } @@ -132,7 +131,8 @@ private void saveSecureStore() throws IOException { if (secureStoreInitData != null) { - File dst = new File(site.lib_dir, secureStoreInitData.jarFile.getName()); + Path dst = + site.lib_dir.resolve(secureStoreInitData.jarFile.getFileName()); Files.copy(secureStoreInitData.jarFile, dst); Section gerritSection = sectionFactory.get("gerrit", null); gerritSection.set("secureStoreClass", secureStoreInitData.className); @@ -140,7 +140,7 @@ } private void extractMailExample(String orig) throws Exception { - File ex = new File(site.mail_dir, orig + ".example"); + Path ex = site.mail_dir.resolve(orig + ".example"); extract(ex, OutgoingEmail.class, orig); chmod(0444, ex); }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java index 8c13540..21cd3c8 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java
@@ -30,13 +30,14 @@ import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.storage.file.FileBasedConfig; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.InetSocketAddress; import java.net.URLDecoder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Map; import java.util.Properties; @@ -64,8 +65,8 @@ private final FileBasedConfig cfg; private final SecureStore sec; - private final File site_path; - private final File etc_dir; + private final Path site_path; + private final Path etc_dir; private final Section.Factory sections; @Inject @@ -82,7 +83,7 @@ boolean isNeedUpgrade() { for (String name : etcFiles) { - if (new File(site_path, name).exists()) { + if (Files.exists(site_path.resolve(name))) { return true; } } @@ -95,19 +96,21 @@ return; } - if (!ui.yesno(true, "Upgrade '%s'", site_path.getCanonicalPath())) { + if (!ui.yesno(true, "Upgrade '%s'", site_path.toAbsolutePath())) { throw die("aborted by user"); } for (String name : etcFiles) { - final File src = new File(site_path, name); - final File dst = new File(etc_dir, name); - if (src.exists()) { - if (dst.exists()) { + Path src = site_path.resolve(name); + Path dst = etc_dir.resolve(name); + if (Files.exists(src)) { + if (Files.exists(dst)) { throw die("File " + src + " would overwrite " + dst); } - if (!src.renameTo(dst)) { - throw die("Cannot rename " + src + " to " + dst); + try { + Files.move(src, dst); + } catch (IOException e) { + throw die("Cannot rename " + src + " to " + dst, e); } } } @@ -256,23 +259,18 @@ private Properties readGerritServerProperties() throws IOException { final Properties srvprop = new Properties(); final String name = System.getProperty("GerritServer"); - File path; + Path path; if (name != null) { - path = new File(name); + path = Paths.get(name); } else { - path = new File(site_path, "GerritServer.properties"); - if (!path.exists()) { - path = new File("GerritServer.properties"); + path = site_path.resolve("GerritServer.properties"); + if (!Files.exists(path)) { + path = Paths.get("GerritServer.properties"); } } - if (path.exists()) { - try { - final InputStream in = new FileInputStream(path); - try { - srvprop.load(in); - } finally { - in.close(); - } + if (Files.exists(path)) { + try (InputStream in = Files.newInputStream(path)) { + srvprop.load(in); } catch (IOException e) { throw new IOException("Cannot read " + name, e); }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/AllProjectsConfig.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/AllProjectsConfig.java index dda536d..10d93ee 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/AllProjectsConfig.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/AllProjectsConfig.java
@@ -40,6 +40,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; public class AllProjectsConfig extends VersionedMetaData { @@ -68,11 +69,11 @@ } private File getPath() { - File basePath = site.resolve(flags.cfg.getString("gerrit", null, "basePath")); + Path basePath = site.resolve(flags.cfg.getString("gerrit", null, "basePath")); if (basePath == null) { throw new IllegalStateException("gerrit.basePath must be configured"); } - return FileKey.resolve(new File(basePath, project), FS.DETECTED); + return FileKey.resolve(basePath.resolve(project).toFile(), FS.DETECTED); } public AllProjectsConfig load() throws IOException, ConfigInvalidException { @@ -136,49 +137,41 @@ throw new IOException("All-Projects does not exist."); } - Repository repo = new FileRepository(path); - try { + try (Repository repo = new FileRepository(path)) { inserter = repo.newObjectInserter(); reader = repo.newObjectReader(); - try { - RevWalk rw = new RevWalk(reader); - try { - RevTree srcTree = revision != null ? rw.parseTree(revision) : null; - newTree = readTree(srcTree); - saveConfig(ProjectConfig.PROJECT_CONFIG, cfg); - saveGroupList(); - ObjectId res = newTree.writeTree(inserter); - if (res.equals(srcTree)) { - // If there are no changes to the content, don't create the commit. - return; - } - - CommitBuilder commit = new CommitBuilder(); - commit.setAuthor(ident); - commit.setCommitter(ident); - commit.setMessage(msg); - commit.setTreeId(res); - if (revision != null) { - commit.addParentId(revision); - } - ObjectId newRevision = inserter.insert(commit); - updateRef(repo, ident, newRevision, "commit: " + msg); - revision = newRevision; - } finally { - rw.release(); + try (RevWalk rw = new RevWalk(reader)) { + RevTree srcTree = revision != null ? rw.parseTree(revision) : null; + newTree = readTree(srcTree); + saveConfig(ProjectConfig.PROJECT_CONFIG, cfg); + saveGroupList(); + ObjectId res = newTree.writeTree(inserter); + if (res.equals(srcTree)) { + // If there are no changes to the content, don't create the commit. + return; } + + CommitBuilder commit = new CommitBuilder(); + commit.setAuthor(ident); + commit.setCommitter(ident); + commit.setMessage(msg); + commit.setTreeId(res); + if (revision != null) { + commit.addParentId(revision); + } + ObjectId newRevision = inserter.insert(commit); + updateRef(repo, ident, newRevision, "commit: " + msg); + revision = newRevision; } finally { if (inserter != null) { - inserter.release(); + inserter.close(); inserter = null; } if (reader != null) { - reader.release(); + reader.close(); reader = null; } } - } finally { - repo.close(); } // we need to invalidate the JGit cache if the group list is invalidated in
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitFlags.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitFlags.java index 2a8155e..07137bc 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitFlags.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitFlags.java
@@ -51,7 +51,7 @@ ConfigInvalidException { sec = secureStore; this.installPlugins = installPlugins; - cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED); + cfg = new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED); cfg.load(); }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitUtil.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitUtil.java index 881208d..904af2f 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitUtil.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/InitUtil.java
@@ -16,14 +16,15 @@ import static com.google.gerrit.common.FileUtil.modified; +import com.google.common.io.ByteStreams; import com.google.gerrit.common.Die; import org.eclipse.jgit.internal.storage.file.LockFile; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; -import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.SystemReader; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -33,7 +34,10 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; -import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.util.Arrays; /** Utility functions to help initialize a site. */ public class InitUtil { @@ -51,9 +55,18 @@ } } - public static void mkdir(final File path) { - if (!path.isDirectory() && !path.mkdir()) { - throw die("Cannot make directory " + path); + public static void mkdir(File file) { + mkdir(file.toPath()); + } + + public static void mkdir(Path path) { + if (Files.isDirectory(path)) { + return; + } + try { + Files.createDirectory(path); + } catch (IOException e) { + throw die("Cannot make directory " + path, e); } } @@ -109,12 +122,11 @@ return name; } - public static void extract(final File dst, final Class<?> sibling, - final String name) throws IOException { + public static void extract(Path dst, Class<?> sibling, String name) + throws IOException { try (InputStream in = open(sibling, name)) { if (in != null) { - ByteBuffer buf = IO.readWholeStream(in, 8192); - copy(dst, buf); + copy(dst, ByteStreams.toByteArray(in)); } } } @@ -136,35 +148,28 @@ return in; } - public static void copy(final File dst, final ByteBuffer buf) + public static void copy(Path dst, byte[] buf) throws FileNotFoundException, IOException { // If the file already has the content we want to put there, // don't attempt to overwrite the file. // - try { - if (buf.equals(ByteBuffer.wrap(IO.readFully(dst)))) { + try (InputStream in = Files.newInputStream(dst)) { + if (Arrays.equals(buf, ByteStreams.toByteArray(in))) { return; } - } catch (FileNotFoundException notFound) { + } catch (NoSuchFileException notFound) { // Fall through and write the file. } - dst.getParentFile().mkdirs(); - LockFile lf = new LockFile(dst, FS.DETECTED); + Files.createDirectories(dst.getParent()); + LockFile lf = new LockFile(dst.toFile(), FS.DETECTED); if (!lf.lock()) { throw new IOException("Cannot lock " + dst); } try { - final OutputStream out = lf.getOutputStream(); - try { - final byte[] tmp = new byte[4096]; - while (0 < buf.remaining()) { - int n = Math.min(buf.remaining(), tmp.length); - buf.get(tmp, 0, n); - out.write(tmp, 0, n); - } - } finally { - out.close(); + try (InputStream in = new ByteArrayInputStream(buf); + OutputStream out = lf.getOutputStream()) { + ByteStreams.copy(in, out); } if (!lf.commit()) { throw new IOException("Cannot commit " + dst);
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/Section.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/Section.java index fbd8ecd..88b084f 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/Section.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/Section.java
@@ -20,7 +20,7 @@ import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; -import java.io.File; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Set; @@ -106,7 +106,7 @@ return nv; } - public File path(final String title, final String name, final String defValue) { + public Path path(final String title, final String name, final String defValue) { return site.resolve(string(title, name, defValue)); }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ErrorLogFile.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ErrorLogFile.java index a766d1e..b8a618b 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ErrorLogFile.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/ErrorLogFile.java
@@ -14,7 +14,7 @@ package com.google.gerrit.pgm.util; -import com.google.gerrit.common.Die; +import com.google.gerrit.common.FileUtil; import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.util.SystemLog; @@ -25,8 +25,8 @@ import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; -import java.io.File; -import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Path; public class ErrorLogFile { static final String LOG_NAME = "error_log"; @@ -47,12 +47,10 @@ root.addAppender(dst); } - public static LifecycleListener start(final File sitePath) - throws FileNotFoundException { - final File logdir = new SitePaths(sitePath).logs_dir; - if (!logdir.exists() && !logdir.mkdirs()) { - throw new Die("Cannot create log directory: " + logdir); - } + public static LifecycleListener start(final Path sitePath) + throws IOException { + Path logdir = FileUtil.mkdirsOrDie(new SitePaths(sitePath).logs_dir, + "Cannot create log directory"); if (SystemLog.shouldConfigure()) { initLogSystem(logdir); } @@ -69,7 +67,7 @@ }; } - private static void initLogSystem(final File logdir) { + private static void initLogSystem(Path logdir) { final Logger root = LogManager.getRootLogger(); root.removeAllAppenders(); root.addAppender(SystemLog.createAppender(logdir, LOG_NAME,
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/GarbageCollectionLogFile.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/GarbageCollectionLogFile.java index 7d33a36..80975a6 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/GarbageCollectionLogFile.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/GarbageCollectionLogFile.java
@@ -14,7 +14,7 @@ package com.google.gerrit.pgm.util; -import com.google.gerrit.common.Die; +import com.google.gerrit.common.FileUtil; import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.git.GarbageCollection; @@ -24,17 +24,13 @@ import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; -import java.io.File; -import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Path; public class GarbageCollectionLogFile { - - public static LifecycleListener start(File sitePath) - throws FileNotFoundException { - File logdir = new SitePaths(sitePath).logs_dir; - if (!logdir.exists() && !logdir.mkdirs()) { - throw new Die("Cannot create log directory: " + logdir); - } + public static LifecycleListener start(Path sitePath) throws IOException { + Path logdir = FileUtil.mkdirsOrDie(new SitePaths(sitePath).logs_dir, + "Cannot create log directory"); if (SystemLog.shouldConfigure()) { initLogSystem(logdir); } @@ -51,7 +47,7 @@ }; } - private static void initLogSystem(File logdir) { + private static void initLogSystem(Path logdir) { Logger gcLogger = LogManager.getLogger(GarbageCollection.LOG_NAME); gcLogger.removeAllAppenders(); gcLogger.addAppender(SystemLog.createAppender(logdir,
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/LogFileCompressor.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/LogFileCompressor.java index db74ac3..1107208 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/LogFileCompressor.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/LogFileCompressor.java
@@ -16,6 +16,7 @@ import static java.util.concurrent.TimeUnit.HOURS; +import com.google.common.io.ByteStreams; import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.lifecycle.LifecycleModule; import com.google.gerrit.server.config.SitePaths; @@ -25,12 +26,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.zip.GZIPOutputStream; /** Compresses the old error logs. */ @@ -65,76 +66,78 @@ } } - private final File logs_dir; + private final Path logs_dir; @Inject LogFileCompressor(final SitePaths site) { logs_dir = resolve(site.logs_dir); } - private static File resolve(final File logs_dir) { + private static Path resolve(Path p) { try { - return logs_dir.getCanonicalFile(); + return p.toRealPath().normalize(); } catch (IOException e) { - return logs_dir.getAbsoluteFile(); + return p.toAbsolutePath().normalize(); } } @Override public void run() { - final File[] list = logs_dir.listFiles(); - if (list == null) { + if (!Files.isDirectory(logs_dir)) { return; } - - for (final File entry : list) { - if (!isLive(entry) && !isCompressed(entry) && isLogFile(entry)) { - compress(entry); + try (DirectoryStream<Path> list = Files.newDirectoryStream(logs_dir)) { + for (Path entry : list) { + if (!isLive(entry) && !isCompressed(entry) && isLogFile(entry)) { + compress(entry); + } } + } catch (IOException e) { + log.error("Error listing logs to compress in " + logs_dir, e); } } - private boolean isLive(final File entry) { - final String name = entry.getName(); + private boolean isLive(Path entry) { + String name = entry.getFileName().toString(); return name.endsWith("_log") || name.endsWith(".log") || name.endsWith(".run") || name.endsWith(".pid"); } - private boolean isCompressed(final File entry) { - final String name = entry.getName(); + private boolean isCompressed(Path entry) { + String name = entry.getFileName().toString(); return name.endsWith(".gz") // || name.endsWith(".zip") // || name.endsWith(".bz2"); } - private boolean isLogFile(final File entry) { - return entry.isFile(); + private boolean isLogFile(Path entry) { + return Files.isRegularFile(entry); } - private void compress(final File src) { - final File dir = src.getParentFile(); - final File dst = new File(dir, src.getName() + ".gz"); - final File tmp = new File(dir, ".tmp." + src.getName()); + private void compress(Path src) { + Path dst = src.resolveSibling(src.getFileName() + ".gz"); + Path tmp = src.resolveSibling(".tmp." + src.getFileName()); try { - try (InputStream in = new FileInputStream(src); - FileOutputStream fo = new FileOutputStream(tmp); - OutputStream out = new GZIPOutputStream(fo)) { - final byte[] buf = new byte[2048]; - int n; - while (0 < (n = in.read(buf))) { - out.write(buf, 0, n); - } - tmp.setReadOnly(); + try (InputStream in = Files.newInputStream(src); + OutputStream out = new GZIPOutputStream(Files.newOutputStream(tmp))) { + ByteStreams.copy(in, out); } - if (!tmp.renameTo(dst)) { - throw new IOException("Cannot rename " + tmp + " to " + dst); + tmp.toFile().setReadOnly(); + try { + Files.move(tmp, dst); + } catch (IOException e) { + throw new IOException("Cannot rename " + tmp + " to " + dst, e); } - src.delete(); + Files.delete(src); } catch (IOException e) { log.error("Cannot compress " + src, e); - tmp.delete(); + try { + Files.deleteIfExists(tmp); + } catch (IOException e2) { + log.warn("Failed to delete temporary log file " + tmp, e2); + } } }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java index c713b79..048c2ee 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java
@@ -24,14 +24,14 @@ import org.eclipse.jgit.lib.Config; -import java.io.File; +import java.nio.file.Path; import javax.sql.DataSource; /** Loads the site library if not yet loaded. */ @Singleton public class SiteLibraryBasedDataSourceProvider extends DataSourceProvider { - private final File libdir; + private final Path libdir; private boolean init; @Inject
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java index 02a8eac..293914b 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -54,9 +54,11 @@ import org.eclipse.jgit.util.FS; import org.kohsuke.args4j.Option; -import java.io.File; import java.io.IOException; import java.lang.annotation.Annotation; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; @@ -66,30 +68,30 @@ public abstract class SiteProgram extends AbstractProgram { @Option(name = "--site-path", aliases = {"-d"}, usage = "Local directory containing site data") - private File sitePath = new File("."); + private void setSitePath(String path) { + sitePath = Paths.get(path); + } protected Provider<DataSource> dsProvider; + private Path sitePath = Paths.get("."); + protected SiteProgram() { } - protected SiteProgram(File sitePath, final Provider<DataSource> dsProvider) { + protected SiteProgram(Path sitePath, final Provider<DataSource> dsProvider) { this.sitePath = sitePath; this.dsProvider = dsProvider; } /** @return the site path specified on the command line. */ - protected File getSitePath() { - File path = sitePath.getAbsoluteFile(); - if (".".equals(path.getName())) { - path = path.getParentFile(); - } - return path; + protected Path getSitePath() { + return sitePath; } /** Ensures we are running inside of a valid site, otherwise throws a Die. */ protected void mustHaveValidSite() throws Die { - if (!new File(new File(getSitePath(), "etc"), "gerrit.config").exists()) { + if (!Files.exists(sitePath.resolve("etc").resolve("gerrit.config"))) { throw die("not a Gerrit site: '" + getSitePath() + "'\n" + "Perhaps you need to run init first?"); } @@ -97,13 +99,13 @@ /** @return provides database connectivity and site path. */ protected Injector createDbInjector(final DataSourceProvider.Context context) { - final File sitePath = getSitePath(); + final Path sitePath = getSitePath(); final List<Module> modules = new ArrayList<>(); Module sitePathModule = new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath); + bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath); bind(String.class).annotatedWith(SecureStoreClassName.class) .toProvider(Providers.of(getConfiguredSecureStoreClass())); } @@ -191,13 +193,14 @@ Module m = new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath); + bind(Path.class).annotatedWith(SitePath.class).toInstance(getSitePath()); bind(SitePaths.class); } }; Injector i = Guice.createInjector(m); SitePaths site = i.getInstance(SitePaths.class); - FileBasedConfig cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED); + FileBasedConfig cfg = + new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED); if (!cfg.getFile().exists()) { return null; } @@ -222,7 +225,7 @@ modules.add(new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath); + bind(Path.class).annotatedWith(SitePath.class).toInstance(getSitePath()); } }); modules.add(new GerritServerConfigModule());
diff --git a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/InitTestCase.java b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/InitTestCase.java index 4d7370b..150309e 100644 --- a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/InitTestCase.java +++ b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/InitTestCase.java
@@ -16,11 +16,11 @@ import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; public abstract class InitTestCase extends LocalDiskRepositoryTestCase { - protected File newSitePath() throws IOException { - return new File(createWorkRepository().getWorkTree(), "test_site"); + protected Path newSitePath() throws IOException { + return createWorkRepository().getWorkTree().toPath().resolve("test_site"); } }
diff --git a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/LibrariesTest.java b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/LibrariesTest.java index a37c97d..2198788 100644 --- a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/LibrariesTest.java +++ b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/LibrariesTest.java
@@ -25,13 +25,12 @@ import org.junit.Test; -import java.io.File; -import java.io.FileNotFoundException; +import java.nio.file.Paths; public class LibrariesTest { @Test - public void testCreate() throws FileNotFoundException { - final SitePaths site = new SitePaths(new File(".")); + public void testCreate() throws Exception { + final SitePaths site = new SitePaths(Paths.get(".")); final ConsoleUI ui = createStrictMock(ConsoleUI.class); replay(ui);
diff --git a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java index 720d108..203da50 100644 --- a/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java +++ b/gerrit-pgm/src/test/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java
@@ -14,6 +14,7 @@ package com.google.gerrit.pgm.init; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.easymock.EasyMock.createStrictMock; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; @@ -24,6 +25,8 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import com.google.common.io.ByteStreams; +import com.google.gerrit.common.FileUtil; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.pgm.init.api.InitFlags; import com.google.gerrit.pgm.init.api.Section; @@ -34,13 +37,12 @@ import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; -import org.eclipse.jgit.util.IO; import org.junit.Test; -import java.io.File; -import java.io.FileWriter; import java.io.IOException; -import java.io.Writer; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collections; import java.util.List; @@ -49,23 +51,17 @@ @Test public void testUpgrade() throws IOException, ConfigInvalidException { - final File p = newSitePath(); + final Path p = newSitePath(); final SitePaths site = new SitePaths(p); assertTrue(site.isNew); - assertTrue(site.site_path.mkdir()); - assertTrue(site.etc_dir.mkdir()); + FileUtil.mkdirsOrDie(site.etc_dir, "Failed to create"); for (String n : UpgradeFrom2_0_x.etcFiles) { - Writer w = new FileWriter(new File(p, n)); - try { - w.write("# " + n + "\n"); - } finally { - w.close(); - } + Files.write(p.resolve(n), ("# " + n + "\n").getBytes(UTF_8)); } FileBasedConfig old = - new FileBasedConfig(new File(p, "gerrit.config"), FS.DETECTED); + new FileBasedConfig(p.resolve("gerrit.config").toFile(), FS.DETECTED); old.setString("ldap", null, "username", "ldap.user"); old.setString("ldap", null, "password", "ldap.s3kr3t"); @@ -85,8 +81,11 @@ } }; - expect(ui.yesno(eq(true), eq("Upgrade '%s'"), eq(p.getCanonicalPath()))) - .andReturn(true); + expect(ui.yesno( + eq(true), + eq("Upgrade '%s'"), + eq(p.toAbsolutePath().normalize()))) + .andReturn(true); replay(ui); UpgradeFrom2_0_x u = new UpgradeFrom2_0_x(site, flags, ui, sections); @@ -98,11 +97,14 @@ for (String n : UpgradeFrom2_0_x.etcFiles) { if ("gerrit.config".equals(n)) continue; if ("secure.config".equals(n)) continue; - assertEquals("# " + n + "\n",// - new String(IO.readFully(new File(site.etc_dir, n)), "UTF-8")); + try (InputStream in = Files.newInputStream(site.etc_dir.resolve(n))) { + assertEquals("# " + n + "\n", + new String(ByteStreams.toByteArray(in), UTF_8)); + } } - FileBasedConfig cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED); + FileBasedConfig cfg = + new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED); cfg.load(); assertEquals("email.user", cfg.getString("sendemail", null, "smtpUser"));
diff --git a/gerrit-plugin-api/pom.xml b/gerrit-plugin-api/pom.xml index 40767e0..eb2ec31 100644 --- a/gerrit-plugin-api/pom.xml +++ b/gerrit-plugin-api/pom.xml
@@ -2,7 +2,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-plugin-api</artifactId> - <version>2.11-SNAPSHOT</version> + <version>2.12-SNAPSHOT</version> <packaging>jar</packaging> <name>Gerrit Code Review - Plugin API</name> <description>API for Gerrit Plugins</description>
diff --git a/gerrit-plugin-archetype/pom.xml b/gerrit-plugin-archetype/pom.xml index b117b29..1da5d51 100644 --- a/gerrit-plugin-archetype/pom.xml +++ b/gerrit-plugin-archetype/pom.xml
@@ -20,7 +20,7 @@ <groupId>com.google.gerrit</groupId> <artifactId>gerrit-plugin-archetype</artifactId> - <version>2.11-SNAPSHOT</version> + <version>2.12-SNAPSHOT</version> <name>Gerrit Code Review - Plugin Archetype</name> <description>Maven Archetype for Gerrit Plugins</description> <url>http://code.google.com/p/gerrit/</url>
diff --git a/gerrit-plugin-gwt-archetype/pom.xml b/gerrit-plugin-gwt-archetype/pom.xml index a7f2bbf..bd4d738 100644 --- a/gerrit-plugin-gwt-archetype/pom.xml +++ b/gerrit-plugin-gwt-archetype/pom.xml
@@ -20,7 +20,7 @@ <groupId>com.google.gerrit</groupId> <artifactId>gerrit-plugin-gwt-archetype</artifactId> - <version>2.11-SNAPSHOT</version> + <version>2.12-SNAPSHOT</version> <name>Gerrit Code Review - Web UI GWT Plugin Archetype</name> <description>Maven Archetype for Gerrit Web UI GWT Plugins</description> <url>http://code.google.com/p/gerrit/</url>
diff --git a/gerrit-plugin-gwtui/pom.xml b/gerrit-plugin-gwtui/pom.xml index fd6fc9b..fa261be 100644 --- a/gerrit-plugin-gwtui/pom.xml +++ b/gerrit-plugin-gwtui/pom.xml
@@ -2,7 +2,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-plugin-gwtui</artifactId> - <version>2.11-SNAPSHOT</version> + <version>2.12-SNAPSHOT</version> <packaging>jar</packaging> <name>Gerrit Code Review - Plugin GWT UI</name> <description>Common Classes for Gerrit GWT UI Plugins</description>
diff --git a/gerrit-plugin-js-archetype/pom.xml b/gerrit-plugin-js-archetype/pom.xml index 796df19..11d4d83 100644 --- a/gerrit-plugin-js-archetype/pom.xml +++ b/gerrit-plugin-js-archetype/pom.xml
@@ -20,7 +20,7 @@ <groupId>com.google.gerrit</groupId> <artifactId>gerrit-plugin-js-archetype</artifactId> - <version>2.11-SNAPSHOT</version> + <version>2.12-SNAPSHOT</version> <name>Gerrit Code Review - Web UI JavaScript Plugin Archetype</name> <description>Maven Archetype for Gerrit Web UI JavaScript Plugins</description> <url>http://code.google.com/p/gerrit/</url>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java b/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java index 8bd082d..019bcab 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java +++ b/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java
@@ -14,7 +14,6 @@ package com.google.gerrit.common; -import com.google.common.base.Strings; import com.google.common.collect.Sets; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.gerrit.common.data.ContributorAgreement; @@ -66,12 +65,14 @@ import org.slf4j.LoggerFactory; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -169,44 +170,44 @@ /** Listeners to receive all changes as they happen. */ private final DynamicSet<EventListener> unrestrictedListeners; - /** Filename of the new patchset hook. */ - private final File patchsetCreatedHook; + /** Path of the new patchset hook. */ + private final Path patchsetCreatedHook; - /** Filename of the draft published hook. */ - private final File draftPublishedHook; + /** Path of the draft published hook. */ + private final Path draftPublishedHook; - /** Filename of the new comments hook. */ - private final File commentAddedHook; + /** Path of the new comments hook. */ + private final Path commentAddedHook; - /** Filename of the change merged hook. */ - private final File changeMergedHook; + /** Path of the change merged hook. */ + private final Path changeMergedHook; - /** Filename of the merge failed hook. */ - private final File mergeFailedHook; + /** Path of the merge failed hook. */ + private final Path mergeFailedHook; - /** Filename of the change abandoned hook. */ - private final File changeAbandonedHook; + /** Path of the change abandoned hook. */ + private final Path changeAbandonedHook; - /** Filename of the change restored hook. */ - private final File changeRestoredHook; + /** Path of the change restored hook. */ + private final Path changeRestoredHook; - /** Filename of the ref updated hook. */ - private final File refUpdatedHook; + /** Path of the ref updated hook. */ + private final Path refUpdatedHook; - /** Filename of the reviewer added hook. */ - private final File reviewerAddedHook; + /** Path of the reviewer added hook. */ + private final Path reviewerAddedHook; - /** Filename of the topic changed hook. */ - private final File topicChangedHook; + /** Path of the topic changed hook. */ + private final Path topicChangedHook; - /** Filename of the cla signed hook. */ - private final File claSignedHook; + /** Path of the cla signed hook. */ + private final Path claSignedHook; - /** Filename of the update hook. */ - private final File refUpdateHook; + /** Path of the update hook. */ + private final Path refUpdateHook; - /** Filename of the hashtags changed hook */ - private final File hashtagsChangedHook; + /** Path of the hashtags changed hook */ + private final Path hashtagsChangedHook; private final String anonymousCowardName; @@ -258,21 +259,30 @@ this.sitePaths = sitePath; this.unrestrictedListeners = unrestrictedListeners; - final File hooksPath = sitePath.resolve(getValue(config, "hooks", "path", sitePath.hooks_dir.getAbsolutePath())); + Path hooksPath; + String hooksPathConfig = config.getString("hooks", null, "path"); + if (hooksPathConfig != null) { + hooksPath = Paths.get(hooksPathConfig); + } else { + hooksPath = sitePath.hooks_dir; + } - patchsetCreatedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "patchsetCreatedHook", "patchset-created")).getPath()); - draftPublishedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "draftPublishedHook", "draft-published")).getPath()); - commentAddedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "commentAddedHook", "comment-added")).getPath()); - changeMergedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "changeMergedHook", "change-merged")).getPath()); - mergeFailedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "mergeFailedHook", "merge-failed")).getPath()); - changeAbandonedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "changeAbandonedHook", "change-abandoned")).getPath()); - changeRestoredHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "changeRestoredHook", "change-restored")).getPath()); - refUpdatedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "refUpdatedHook", "ref-updated")).getPath()); - reviewerAddedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "reviewerAddedHook", "reviewer-added")).getPath()); - topicChangedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "topicChangedHook", "topic-changed")).getPath()); - claSignedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "claSignedHook", "cla-signed")).getPath()); - refUpdateHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "refUpdateHook", "ref-update")).getPath()); - hashtagsChangedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "hashtagsChangedHook", "hashtags-changed")).getPath()); + // When adding a new hook, make sure to check that the setting name + // canonicalizes correctly in hook() below. + patchsetCreatedHook = hook(config, hooksPath, "patchset-created"); + draftPublishedHook = hook(config, hooksPath, "draft-published"); + commentAddedHook = hook(config, hooksPath, "comment-added"); + changeMergedHook = hook(config, hooksPath, "change-merged"); + mergeFailedHook = hook(config, hooksPath, "merge-failed"); + changeAbandonedHook = hook(config, hooksPath, "change-abandoned"); + changeRestoredHook = hook(config, hooksPath, "change-restored"); + refUpdatedHook = hook(config, hooksPath, "ref-updated"); + reviewerAddedHook = hook(config, hooksPath, "reviewer-added"); + topicChangedHook = hook(config, hooksPath, "topic-changed"); + claSignedHook = hook(config, hooksPath, "cla-signed"); + refUpdateHook = hook(config, hooksPath, "ref-update"); + hashtagsChangedHook = hook(config, hooksPath, "hashtags-changed"); + syncHookTimeout = config.getInt("hooks", "syncHookTimeout", 30); syncHookThreadPool = Executors.newCachedThreadPool( new ThreadFactoryBuilder() @@ -280,6 +290,12 @@ .build()); } + private static Path hook(Config config, Path path, String name) { + String setting = name.replace("-", "") + "hook"; + String value = config.getString("hooks", null, setting); + return path.resolve(value != null ? value : name); + } + @Override public void addEventListener(EventListener listener, CurrentUser user) { listeners.put(listener, new EventListenerHolder(listener, user)); @@ -291,20 +307,6 @@ } /** - * Helper Method for getting values from the config. - * - * @param config Config file to get value from. - * @param section Section to look in. - * @param setting Setting to get. - * @param fallback Fallback value. - * @return Setting value if found, else fallback. - */ - private String getValue(final Config config, final String section, final String setting, final String fallback) { - final String result = config.getString(section, null, setting); - return Strings.isNullOrEmpty(result) ? fallback : result; - } - - /** * Get the Repository for the given project name, or null on error. * * @param name Project to get repo for, @@ -788,23 +790,23 @@ * @param hook the hook to execute. * @param args Arguments to use to run the hook. */ - private synchronized void runHook(Project.NameKey project, File hook, + private synchronized void runHook(Project.NameKey project, Path hook, List<String> args) { - if (project != null && hook.exists()) { + if (project != null && Files.exists(hook)) { hookQueue.execute(new AsyncHookTask(project, hook, args)); } } - private synchronized void runHook(File hook, List<String> args) { - if (hook.exists()) { + private synchronized void runHook(Path hook, List<String> args) { + if (Files.exists(hook)) { hookQueue.execute(new AsyncHookTask(null, hook, args)); } } private HookResult runSyncHook(Project.NameKey project, - File hook, List<String> args) { + Path hook, List<String> args) { - if (!hook.exists()) { + if (!Files.exists(hook)) { return null; } @@ -818,10 +820,10 @@ try { return task.get(syncHookTimeout, TimeUnit.SECONDS); } catch (TimeoutException e) { - message = "Synchronous hook timed out " + hook.getAbsolutePath(); + message = "Synchronous hook timed out " + hook.toAbsolutePath(); log.error(message); } catch (Exception e) { - message = "Error running hook " + hook.getAbsolutePath(); + message = "Error running hook " + hook.toAbsolutePath(); log.error(message, e); } @@ -849,12 +851,12 @@ private class HookTask { private final Project.NameKey project; - private final File hook; + private final Path hook; private final List<String> args; private StringWriter output; private Process ps; - protected HookTask(Project.NameKey project, File hook, List<String> args) { + protected HookTask(Project.NameKey project, Path hook, List<String> args) { this.project = project; this.hook = hook; this.args = args; @@ -870,7 +872,7 @@ try { final List<String> argv = new ArrayList<>(1 + args.size()); - argv.add(hook.getAbsolutePath()); + argv.add(hook.toAbsolutePath().toString()); argv.addAll(args); final ProcessBuilder pb = new ProcessBuilder(argv); @@ -881,7 +883,7 @@ } final Map<String, String> env = pb.environment(); - env.put("GERRIT_SITE", sitePaths.site_path.getAbsolutePath()); + env.put("GERRIT_SITE", sitePaths.site_path.toAbsolutePath().toString()); if (repo != null) { pb.directory(repo.getDirectory()); @@ -906,7 +908,7 @@ } catch (InterruptedException iex) { // InterruptedExeception - timeout or cancel } catch (Throwable err) { - log.error("Error running hook " + hook.getAbsolutePath(), err); + log.error("Error running hook " + hook.toAbsolutePath(), err); } finally { if (repo != null) { repo.close(); @@ -949,12 +951,12 @@ } protected String getName() { - return hook.getName(); + return hook.getFileName().toString(); } @Override public String toString() { - return "hook " + hook.getName(); + return "hook " + hook.getFileName(); } public void cancel() { @@ -966,7 +968,7 @@ private final class SyncHookTask extends HookTask implements Callable<HookResult> { - private SyncHookTask(Project.NameKey project, File hook, List<String> args) { + private SyncHookTask(Project.NameKey project, Path hook, List<String> args) { super(project, hook, args); } @@ -979,7 +981,7 @@ /** Runnable type used to run asynchronous hooks */ private final class AsyncHookTask extends HookTask implements Runnable { - private AsyncHookTask(Project.NameKey project, File hook, List<String> args) { + private AsyncHookTask(Project.NameKey project, Path hook, List<String> args) { super(project, hook, args); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/rules/PrologCompiler.java b/gerrit-server/src/main/java/com/google/gerrit/rules/PrologCompiler.java index 4724bc2..f012bd30 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/rules/PrologCompiler.java +++ b/gerrit-server/src/main/java/com/google/gerrit/rules/PrologCompiler.java
@@ -14,6 +14,8 @@ package com.google.gerrit.rules; +import static java.nio.file.StandardOpenOption.DELETE_ON_CLOSE; + import com.google.gerrit.common.TimeUtil; import com.google.gerrit.common.Version; import com.google.gerrit.reviewdb.client.RefNames; @@ -35,8 +37,11 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -67,14 +72,14 @@ NO_RULES, COMPILED } - private final File ruleDir; + private final Path ruleDir; private final Repository git; @Inject PrologCompiler(@GerritServerConfig Config config, SitePaths site, @Assisted Repository gitRepository) { - File cacheDir = site.resolve(config.getString("cache", null, "directory")); - ruleDir = cacheDir != null ? new File(cacheDir, "rules") : null; + Path cacheDir = site.resolve(config.getString("cache", null, "directory")); + ruleDir = cacheDir != null ? cacheDir.resolve("rules") : null; git = gitRepository; } @@ -93,7 +98,9 @@ if (ruleDir == null) { throw new CompileException("Caching not enabled"); } - if (!ruleDir.isDirectory() && !ruleDir.mkdir()) { + try { + Files.createDirectory(ruleDir); + } catch (IOException e) { throw new IOException("Cannot create " + ruleDir); } @@ -111,9 +118,9 @@ compileProlog(rulesId, tempDir); compileJava(tempDir); - File jarFile = new File(ruleDir, "rules-" + rulesId.getName() + ".jar"); + Path jarPath = ruleDir.resolve("rules-" + rulesId.getName() + ".jar"); List<String> classFiles = getRelativePaths(tempDir, ".class"); - createJar(jarFile, classFiles, tempDir, metaConfig, rulesId); + createJar(jarPath, classFiles, tempDir, metaConfig, rulesId); return Status.COMPILED; } finally { @@ -222,51 +229,51 @@ } /** Takes compiled prolog .class files, puts them into the jar file. */ - private void createJar(File archiveFile, List<String> toBeJared, + private void createJar(Path archiveFile, List<String> toBeJared, File tempDir, ObjectId metaConfig, ObjectId rulesId) throws IOException { long now = TimeUtil.nowMs(); - File tmpjar = File.createTempFile(".rulec_", ".jar", archiveFile.getParentFile()); - try { - Manifest mf = new Manifest(); - mf.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); - mf.getMainAttributes().putValue("Built-by", "Gerrit Code Review " + Version.getVersion()); - if (git.getDirectory() != null) { - mf.getMainAttributes().putValue("Source-Repository", git.getDirectory().getPath()); - } - mf.getMainAttributes().putValue("Source-Commit", metaConfig.name()); - mf.getMainAttributes().putValue("Source-Blob", rulesId.name()); + Manifest mf = new Manifest(); + mf.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + mf.getMainAttributes().putValue("Built-by", "Gerrit Code Review " + Version.getVersion()); + if (git.getDirectory() != null) { + mf.getMainAttributes().putValue("Source-Repository", git.getDirectory().getPath()); + } + mf.getMainAttributes().putValue("Source-Commit", metaConfig.name()); + mf.getMainAttributes().putValue("Source-Blob", rulesId.name()); - try (FileOutputStream stream = new FileOutputStream(tmpjar); - JarOutputStream out = new JarOutputStream(stream, mf)) { - byte buffer[] = new byte[10240]; - for (String path : toBeJared) { - JarEntry jarAdd = new JarEntry(path); - File f = new File(tempDir, path); - jarAdd.setTime(now); - out.putNextEntry(jarAdd); - if (f.isFile()) { - FileInputStream in = new FileInputStream(f); - try { - while (true) { - int nRead = in.read(buffer, 0, buffer.length); - if (nRead <= 0) { - break; - } - out.write(buffer, 0, nRead); + Path tmpjar = + Files.createTempFile(archiveFile.getParent(), ".rulec_", ".jar"); + try (OutputStream stream = Files.newOutputStream(tmpjar, DELETE_ON_CLOSE); + JarOutputStream out = new JarOutputStream(stream, mf)) { + byte buffer[] = new byte[10240]; + // TODO: fixify this loop + for (String path : toBeJared) { + JarEntry jarAdd = new JarEntry(path); + File f = new File(tempDir, path); + jarAdd.setTime(now); + out.putNextEntry(jarAdd); + if (f.isFile()) { + FileInputStream in = new FileInputStream(f); + try { + while (true) { + int nRead = in.read(buffer, 0, buffer.length); + if (nRead <= 0) { + break; } - } finally { - in.close(); + out.write(buffer, 0, nRead); } + } finally { + in.close(); } - out.closeEntry(); } + out.closeEntry(); } + } - if (!tmpjar.renameTo(archiveFile)) { - throw new IOException("Cannot replace " + archiveFile); - } - } finally { - tmpjar.delete(); + try { + Files.move(tmpjar, archiveFile); + } catch (IOException e) { + throw new IOException("Cannot replace " + archiveFile, e); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java b/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java index 5dea6a2..ced7fc7 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java +++ b/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java
@@ -44,7 +44,6 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.util.RawParseUtils; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -57,6 +56,8 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.EnumSet; import java.util.HashMap; import java.util.List; @@ -96,8 +97,8 @@ } private final boolean enableProjectRules; - private final File cacheDir; - private final File rulesDir; + private final Path cacheDir; + private final Path rulesDir; private final GitRepositoryManager gitMgr; private final DynamicSet<PredicateProvider> predicateProviders; private final ClassLoader systemLoader; @@ -108,7 +109,7 @@ GitRepositoryManager gm, DynamicSet<PredicateProvider> predicateProviders) { enableProjectRules = config.getBoolean("rules", null, "enable", true); cacheDir = site.resolve(config.getString("cache", null, "directory")); - rulesDir = cacheDir != null ? new File(cacheDir, "rules") : null; + rulesDir = cacheDir != null ? cacheDir.resolve("rules") : null; gitMgr = gm; this.predicateProviders = predicateProviders; @@ -178,9 +179,9 @@ // that over dynamic consult as the bytecode will be faster. // if (rulesDir != null) { - File jarFile = new File(rulesDir, "rules-" + rulesId.getName() + ".jar"); - if (jarFile.isFile()) { - URL[] cp = new URL[] {toURL(jarFile)}; + Path jarPath = rulesDir.resolve("rules-" + rulesId.getName() + ".jar"); + if (Files.isRegularFile(jarPath)) { + URL[] cp = new URL[] {toURL(jarPath)}; return save(newEmptyMachine(new URLClassLoader(cp, systemLoader))); } } @@ -254,11 +255,11 @@ return ctl; } - private static URL toURL(File jarFile) throws CompileException { + private static URL toURL(Path jarPath) throws CompileException { try { - return jarFile.toURI().toURL(); + return jarPath.toUri().toURL(); } catch (MalformedURLException e) { - throw new CompileException("Cannot create URL for " + jarFile, e); + throw new CompileException("Cannot create URL for " + jarPath, e); } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java index 93bbd7b..9faa516 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
@@ -26,6 +26,7 @@ import com.google.gerrit.reviewdb.client.ChangeMessage; import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSetAncestor; +import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.RevId; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.change.ChangeInserter; @@ -227,119 +228,107 @@ } Change changeToRevert = db.get().changes().get(changeId); - Repository git; - try { - git = gitManager.openRepository(ctl.getChange().getProject()); + Project.NameKey project = ctl.getChange().getProject(); + try (Repository git = gitManager.openRepository(project); + RevWalk revWalk = new RevWalk(git)) { + RevCommit commitToRevert = + revWalk.parseCommit(ObjectId.fromString(patch.getRevision().get())); + + PersonIdent authorIdent = + user().newCommitterIdent(myIdent.getWhen(), myIdent.getTimeZone()); + + RevCommit parentToCommitToRevert = commitToRevert.getParent(0); + revWalk.parseHeaders(parentToCommitToRevert); + + CommitBuilder revertCommitBuilder = new CommitBuilder(); + revertCommitBuilder.addParentId(commitToRevert); + revertCommitBuilder.setTreeId(parentToCommitToRevert.getTree()); + revertCommitBuilder.setAuthor(authorIdent); + revertCommitBuilder.setCommitter(authorIdent); + + if (message == null) { + message = MessageFormat.format( + ChangeMessages.get().revertChangeDefaultMessage, + changeToRevert.getSubject(), patch.getRevision().get()); + } + + ObjectId computedChangeId = + ChangeIdUtil.computeChangeId(parentToCommitToRevert.getTree(), + commitToRevert, authorIdent, myIdent, message); + revertCommitBuilder.setMessage( + ChangeIdUtil.insertId(message, computedChangeId, true)); + + RevCommit revertCommit; + try (ObjectInserter oi = git.newObjectInserter()) { + ObjectId id = oi.insert(revertCommitBuilder); + oi.flush(); + revertCommit = revWalk.parseCommit(id); + } + + RefControl refControl = ctl.getRefControl(); + Change change = new Change( + new Change.Key("I" + computedChangeId.name()), + new Change.Id(db.get().nextChangeId()), + user().getAccountId(), + changeToRevert.getDest(), + TimeUtil.nowTs()); + change.setTopic(changeToRevert.getTopic()); + ChangeInserter ins = + changeInserterFactory.create(refControl.getProjectControl(), + change, revertCommit); + PatchSet ps = ins.getPatchSet(); + + String ref = refControl.getRefName(); + String cmdRef = MagicBranch.NEW_PUBLISH_CHANGE + + ref.substring(ref.lastIndexOf('/') + 1); + CommitReceivedEvent commitReceivedEvent = new CommitReceivedEvent( + new ReceiveCommand(ObjectId.zeroId(), revertCommit.getId(), cmdRef), + refControl.getProjectControl().getProject(), + refControl.getRefName(), revertCommit, user()); + + try { + commitValidatorsFactory.create(refControl, sshInfo, git) + .validateForGerritCommits(commitReceivedEvent); + } catch (CommitValidationException e) { + throw new InvalidChangeOperationException(e.getMessage()); + } + + RefUpdate ru = git.updateRef(ps.getRefName()); + ru.setExpectedOldObjectId(ObjectId.zeroId()); + ru.setNewObjectId(revertCommit); + ru.disableRefLog(); + if (ru.update(revWalk) != RefUpdate.Result.NEW) { + throw new IOException(String.format( + "Failed to create ref %s in %s: %s", ps.getRefName(), + change.getDest().getParentKey().get(), ru.getResult())); + } + + ChangeMessage cmsg = new ChangeMessage( + new ChangeMessage.Key(changeId, messageUUID(db.get())), + user().getAccountId(), TimeUtil.nowTs(), patchSetId); + StringBuilder msgBuf = new StringBuilder(); + msgBuf.append("Patch Set ").append(patchSetId.get()).append(": Reverted"); + msgBuf.append("\n\n"); + msgBuf.append("This patchset was reverted in change: ") + .append(change.getKey().get()); + cmsg.setMessage(msgBuf.toString()); + + ins.setMessage(cmsg).insert(); + + try { + RevertedSender cm = revertedSenderFactory.create(change); + cm.setFrom(user().getAccountId()); + cm.setChangeMessage(cmsg); + cm.send(); + } catch (Exception err) { + log.error("Cannot send email for revert change " + change.getId(), + err); + } + + return change.getId(); } catch (RepositoryNotFoundException e) { throw new NoSuchChangeException(changeId, e); } - try { - RevWalk revWalk = new RevWalk(git); - try { - RevCommit commitToRevert = - revWalk.parseCommit(ObjectId.fromString(patch.getRevision().get())); - - PersonIdent authorIdent = - user().newCommitterIdent(myIdent.getWhen(), myIdent.getTimeZone()); - - RevCommit parentToCommitToRevert = commitToRevert.getParent(0); - revWalk.parseHeaders(parentToCommitToRevert); - - CommitBuilder revertCommitBuilder = new CommitBuilder(); - revertCommitBuilder.addParentId(commitToRevert); - revertCommitBuilder.setTreeId(parentToCommitToRevert.getTree()); - revertCommitBuilder.setAuthor(authorIdent); - revertCommitBuilder.setCommitter(authorIdent); - - if (message == null) { - message = MessageFormat.format( - ChangeMessages.get().revertChangeDefaultMessage, - changeToRevert.getSubject(), patch.getRevision().get()); - } - - ObjectId computedChangeId = - ChangeIdUtil.computeChangeId(parentToCommitToRevert.getTree(), - commitToRevert, authorIdent, myIdent, message); - revertCommitBuilder.setMessage( - ChangeIdUtil.insertId(message, computedChangeId, true)); - - RevCommit revertCommit; - ObjectInserter oi = git.newObjectInserter(); - try { - ObjectId id = oi.insert(revertCommitBuilder); - oi.flush(); - revertCommit = revWalk.parseCommit(id); - } finally { - oi.release(); - } - - RefControl refControl = ctl.getRefControl(); - Change change = new Change( - new Change.Key("I" + computedChangeId.name()), - new Change.Id(db.get().nextChangeId()), - user().getAccountId(), - changeToRevert.getDest(), - TimeUtil.nowTs()); - change.setTopic(changeToRevert.getTopic()); - ChangeInserter ins = - changeInserterFactory.create(refControl.getProjectControl(), - change, revertCommit); - PatchSet ps = ins.getPatchSet(); - - String ref = refControl.getRefName(); - String cmdRef = MagicBranch.NEW_PUBLISH_CHANGE - + ref.substring(ref.lastIndexOf('/') + 1); - CommitReceivedEvent commitReceivedEvent = new CommitReceivedEvent( - new ReceiveCommand(ObjectId.zeroId(), revertCommit.getId(), cmdRef), - refControl.getProjectControl().getProject(), - refControl.getRefName(), revertCommit, user()); - - try { - commitValidatorsFactory.create(refControl, sshInfo, git) - .validateForGerritCommits(commitReceivedEvent); - } catch (CommitValidationException e) { - throw new InvalidChangeOperationException(e.getMessage()); - } - - RefUpdate ru = git.updateRef(ps.getRefName()); - ru.setExpectedOldObjectId(ObjectId.zeroId()); - ru.setNewObjectId(revertCommit); - ru.disableRefLog(); - if (ru.update(revWalk) != RefUpdate.Result.NEW) { - throw new IOException(String.format( - "Failed to create ref %s in %s: %s", ps.getRefName(), - change.getDest().getParentKey().get(), ru.getResult())); - } - - ChangeMessage cmsg = new ChangeMessage( - new ChangeMessage.Key(changeId, messageUUID(db.get())), - user().getAccountId(), TimeUtil.nowTs(), patchSetId); - StringBuilder msgBuf = new StringBuilder(); - msgBuf.append("Patch Set ").append(patchSetId.get()).append(": Reverted"); - msgBuf.append("\n\n"); - msgBuf.append("This patchset was reverted in change: ") - .append(change.getKey().get()); - cmsg.setMessage(msgBuf.toString()); - - ins.setMessage(cmsg).insert(); - - try { - RevertedSender cm = revertedSenderFactory.create(change); - cm.setFrom(user().getAccountId()); - cm.setChangeMessage(cmsg); - cm.send(); - } catch (Exception err) { - log.error("Cannot send email for revert change " + change.getId(), - err); - } - - return change.getId(); - } finally { - revWalk.release(); - } - } finally { - git.close(); - } } public Change.Id editCommitMessage(ChangeControl ctl, PatchSet ps, @@ -354,68 +343,56 @@ "The commit message cannot be empty"); } - Repository git; - try { - git = gitManager.openRepository(ctl.getChange().getProject()); + Project.NameKey project = ctl.getChange().getProject(); + try (Repository git = gitManager.openRepository(project); + RevWalk revWalk = new RevWalk(git)) { + RevCommit commit = + revWalk.parseCommit(ObjectId.fromString(ps.getRevision() + .get())); + if (commit.getFullMessage().equals(message)) { + throw new InvalidChangeOperationException( + "New commit message cannot be same as existing commit message"); + } + + Date now = myIdent.getWhen(); + PersonIdent authorIdent = + user().newCommitterIdent(now, myIdent.getTimeZone()); + + CommitBuilder commitBuilder = new CommitBuilder(); + commitBuilder.setTreeId(commit.getTree()); + commitBuilder.setParentIds(commit.getParents()); + commitBuilder.setAuthor(commit.getAuthorIdent()); + commitBuilder.setCommitter(authorIdent); + commitBuilder.setMessage(message); + + RevCommit newCommit; + try (ObjectInserter oi = git.newObjectInserter()) { + ObjectId id = oi.insert(commitBuilder); + oi.flush(); + newCommit = revWalk.parseCommit(id); + } + + PatchSet.Id id = nextPatchSetId(git, change.currentPatchSetId()); + PatchSet newPatchSet = new PatchSet(id); + newPatchSet.setCreatedOn(new Timestamp(now.getTime())); + newPatchSet.setUploader(user().getAccountId()); + newPatchSet.setRevision(new RevId(newCommit.name())); + + String msg = "Patch Set " + newPatchSet.getPatchSetId() + + ": Commit message was updated"; + + change = patchSetInserterFactory + .create(git, revWalk, ctl, newCommit) + .setPatchSet(newPatchSet) + .setMessage(msg) + .setValidatePolicy(RECEIVE_COMMITS) + .setDraft(ps.isDraft()) + .insert(); + + return change.getId(); } catch (RepositoryNotFoundException e) { throw new NoSuchChangeException(changeId, e); } - try { - RevWalk revWalk = new RevWalk(git); - try { - RevCommit commit = - revWalk.parseCommit(ObjectId.fromString(ps.getRevision() - .get())); - if (commit.getFullMessage().equals(message)) { - throw new InvalidChangeOperationException( - "New commit message cannot be same as existing commit message"); - } - - Date now = myIdent.getWhen(); - PersonIdent authorIdent = - user().newCommitterIdent(now, myIdent.getTimeZone()); - - CommitBuilder commitBuilder = new CommitBuilder(); - commitBuilder.setTreeId(commit.getTree()); - commitBuilder.setParentIds(commit.getParents()); - commitBuilder.setAuthor(commit.getAuthorIdent()); - commitBuilder.setCommitter(authorIdent); - commitBuilder.setMessage(message); - - RevCommit newCommit; - ObjectInserter oi = git.newObjectInserter(); - try { - ObjectId id = oi.insert(commitBuilder); - oi.flush(); - newCommit = revWalk.parseCommit(id); - } finally { - oi.release(); - } - - PatchSet.Id id = nextPatchSetId(git, change.currentPatchSetId()); - PatchSet newPatchSet = new PatchSet(id); - newPatchSet.setCreatedOn(new Timestamp(now.getTime())); - newPatchSet.setUploader(user().getAccountId()); - newPatchSet.setRevision(new RevId(newCommit.name())); - - String msg = "Patch Set " + newPatchSet.getPatchSetId() - + ": Commit message was updated"; - - change = patchSetInserterFactory - .create(git, revWalk, ctl, newCommit) - .setPatchSet(newPatchSet) - .setMessage(msg) - .setValidatePolicy(RECEIVE_COMMITS) - .setDraft(ps.isDraft()) - .insert(); - - return change.getId(); - } finally { - revWalk.release(); - } - } finally { - git.close(); - } } public String getMessage(Change change) @@ -427,25 +404,14 @@ throw new NoSuchChangeException(changeId); } - Repository git; - try { - git = gitManager.openRepository(change.getProject()); + try (Repository git = gitManager.openRepository(change.getProject()); + RevWalk revWalk = new RevWalk(git)) { + RevCommit commit = revWalk.parseCommit( + ObjectId.fromString(ps.getRevision().get())); + return commit.getFullMessage(); } catch (RepositoryNotFoundException e) { throw new NoSuchChangeException(changeId, e); } - try { - RevWalk revWalk = new RevWalk(git); - try { - RevCommit commit = - revWalk.parseCommit(ObjectId.fromString(ps.getRevision() - .get())); - return commit.getFullMessage(); - } finally { - revWalk.release(); - } - } finally { - git.close(); - } } public void deleteDraftChange(Change change)
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/SuggestAccounts.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/SuggestAccounts.java index 07936d9..d181c35 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/SuggestAccounts.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/SuggestAccounts.java
@@ -39,7 +39,7 @@ import java.util.List; import java.util.Map; -class SuggestAccounts implements RestReadView<TopLevelResource> { +public class SuggestAccounts implements RestReadView<TopLevelResource> { private static final int MAX_RESULTS = 100; private static final String MAX_SUFFIX = "\u9fa5"; @@ -50,9 +50,10 @@ private final int suggestFrom; private int limit = 10; + private String query; @Option(name = "--limit", aliases = {"-n"}, metaVar = "CNT", usage = "maximum number of users to return") - void setLimit(int n) { + public void setLimit(int n) { if (n < 0) { limit = 10; } else if (n == 0) { @@ -63,7 +64,9 @@ } @Option(name = "--query", aliases = {"-q"}, metaVar = "QUERY", usage = "match users") - private String query; + public void setQuery(String query) { + this.query = query; + } @Inject SuggestAccounts(AccountControl.Factory accountControlFactory,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java index 0c02c99..cf041fd 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/accounts/AccountsImpl.java
@@ -16,6 +16,7 @@ import com.google.gerrit.extensions.api.accounts.AccountApi; import com.google.gerrit.extensions.api.accounts.Accounts; +import com.google.gerrit.extensions.common.AccountInfo; import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.extensions.restapi.IdString; import com.google.gerrit.extensions.restapi.RestApiException; @@ -24,24 +25,30 @@ import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.account.AccountResource; import com.google.gerrit.server.account.AccountsCollection; +import com.google.gerrit.server.account.SuggestAccounts; import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; +import java.util.List; + @Singleton public class AccountsImpl extends Accounts.NotImplemented implements Accounts { private final AccountsCollection accounts; private final AccountApiImpl.Factory api; private final Provider<CurrentUser> self; + private final Provider<SuggestAccounts> suggestAccountsProvider; @Inject AccountsImpl(AccountsCollection accounts, AccountApiImpl.Factory api, - Provider<CurrentUser> self) { + Provider<CurrentUser> self, + Provider<SuggestAccounts> suggestAccountsProvider) { this.accounts = accounts; this.api = api; this.self = self; + this.suggestAccountsProvider = suggestAccountsProvider; } @Override @@ -61,4 +68,32 @@ } return api.create(new AccountResource((IdentifiedUser)self.get())); } + + @Override + public SuggestAccountsRequest suggestAccounts() throws RestApiException { + return new SuggestAccountsRequest() { + @Override + public List<AccountInfo> get() throws RestApiException { + return AccountsImpl.this.suggestAccounts(this); + } + }; + } + + @Override + public SuggestAccountsRequest suggestAccounts(String query) + throws RestApiException { + return suggestAccounts().withQuery(query); + } + + private List<AccountInfo> suggestAccounts(SuggestAccountsRequest r) + throws RestApiException { + try { + SuggestAccounts mySuggestAccounts = suggestAccountsProvider.get(); + mySuggestAccounts.setQuery(r.getQuery()); + mySuggestAccounts.setLimit(r.getLimit()); + return mySuggestAccounts.apply(TopLevelResource.INSTANCE); + } catch (OrmException e) { + throw new RestApiException("Cannot retrieve suggested accounts", e); + } + } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java index 76cf49c..23039aa 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeKindCacheImpl.java
@@ -189,8 +189,7 @@ return ChangeKind.NO_CODE_CHANGE; } - RevWalk walk = new RevWalk(key.repo); - try { + try (RevWalk walk = new RevWalk(key.repo)) { RevCommit prior = walk.parseCommit(key.prior); walk.parseBody(prior); RevCommit next = walk.parseCommit(key.next); @@ -227,7 +226,6 @@ } } finally { key.repo = null; - walk.release(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java index 16472e3..1555cdd 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeResource.java
@@ -57,17 +57,15 @@ return getControl().getNotes(); } - @Override - public String getETag() { - CurrentUser user = control.getCurrentUser(); - Hasher h = Hashing.md5().newHasher() - .putLong(getChange().getLastUpdatedOn().getTime()) + + // This includes all information relevant for ETag computation + // unrelated to the UI. + public void prepareETag(Hasher h, CurrentUser user) { + h.putLong(getChange().getLastUpdatedOn().getTime()) .putInt(getChange().getRowVersion()) - .putBoolean(user.getStarredChanges().contains(getChange().getId())) .putInt(user.isIdentifiedUser() ? ((IdentifiedUser) user).getAccountId().get() : 0); - byte[] buf = new byte[20]; ObjectId noteId; try { @@ -82,6 +80,14 @@ for (ProjectState p : control.getProjectControl().getProjectState().tree()) { hashObjectId(h, p.getConfig().getRevision(), buf); } + } + + @Override + public String getETag() { + CurrentUser user = control.getCurrentUser(); + Hasher h = Hashing.md5().newHasher() + .putBoolean(user.getStarredChanges().contains(getChange().getId())); + prepareETag(h, user); return h.hash().toString(); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java index efcd6d9..f4d1e0a 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java
@@ -102,6 +102,7 @@ return new UiAction.Description() .setLabel("Cherry Pick") .setTitle("Cherry pick change to a different branch") - .setVisible(resource.getControl().getProjectControl().canUpload()); + .setVisible(resource.getControl().getProjectControl().canUpload() + && resource.isCurrent()); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java index 48944fa..b386894 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java
@@ -121,96 +121,82 @@ Project.NameKey project = change.getProject(); IdentifiedUser identifiedUser = (IdentifiedUser) currentUser.get(); - final Repository git; - try { - git = gitManager.openRepository(project); + try (Repository git = gitManager.openRepository(project); + RevWalk revWalk = new RevWalk(git)) { + Ref destRef = git.getRef(destinationBranch); + if (destRef == null) { + throw new InvalidChangeOperationException("Branch " + + destinationBranch + " does not exist."); + } + + final RevCommit mergeTip = revWalk.parseCommit(destRef.getObjectId()); + + RevCommit commitToCherryPick = + revWalk.parseCommit(ObjectId.fromString(patch.getRevision().get())); + + PersonIdent committerIdent = + identifiedUser.newCommitterIdent(TimeUtil.nowTs(), + serverTimeZone); + + final ObjectId computedChangeId = + ChangeIdUtil + .computeChangeId(commitToCherryPick.getTree(), mergeTip, + commitToCherryPick.getAuthorIdent(), committerIdent, message); + String commitMessage = + ChangeIdUtil.insertId(message, computedChangeId).trim() + '\n'; + + RevCommit cherryPickCommit; + try (ObjectInserter oi = git.newObjectInserter()) { + ProjectState projectState = refControl.getProjectControl().getProjectState(); + cherryPickCommit = + mergeUtilFactory.create(projectState).createCherryPickFromCommit(git, oi, mergeTip, + commitToCherryPick, committerIdent, commitMessage, revWalk); + } catch (MergeIdenticalTreeException | MergeConflictException e) { + throw new MergeException("Cherry pick failed: " + e.getMessage()); + } + + Change.Key changeKey; + final List<String> idList = cherryPickCommit.getFooterLines( + FooterConstants.CHANGE_ID); + if (!idList.isEmpty()) { + final String idStr = idList.get(idList.size() - 1).trim(); + changeKey = new Change.Key(idStr); + } else { + changeKey = new Change.Key("I" + computedChangeId.name()); + } + + Branch.NameKey newDest = + new Branch.NameKey(change.getProject(), destRef.getName()); + List<ChangeData> destChanges = queryProvider.get() + .setLimit(2) + .byBranchKey(newDest, changeKey); + if (destChanges.size() > 1) { + throw new InvalidChangeOperationException("Several changes with key " + + changeKey + " reside on the same branch. " + + "Cannot create a new patch set."); + } else if (destChanges.size() == 1) { + // The change key exists on the destination branch. The cherry pick + // will be added as a new patch set. + return insertPatchSet(git, revWalk, destChanges.get(0).change(), + cherryPickCommit, refControl, identifiedUser); + } else { + // Change key not found on destination branch. We can create a new + // change. + Change newChange = createNewChange(git, revWalk, changeKey, project, + destRef, cherryPickCommit, refControl, + identifiedUser, change.getTopic()); + + addMessageToSourceChange(change, patch.getId(), destinationBranch, + cherryPickCommit, identifiedUser, refControl); + + addMessageToDestinationChange(newChange, change.getDest().getShortName(), + identifiedUser, refControl); + + return newChange.getId(); + } } catch (RepositoryNotFoundException e) { throw new NoSuchChangeException(change.getId(), e); } - - try { - RevWalk revWalk = new RevWalk(git); - try { - Ref destRef = git.getRef(destinationBranch); - if (destRef == null) { - throw new InvalidChangeOperationException("Branch " - + destinationBranch + " does not exist."); - } - - final RevCommit mergeTip = revWalk.parseCommit(destRef.getObjectId()); - - RevCommit commitToCherryPick = - revWalk.parseCommit(ObjectId.fromString(patch.getRevision().get())); - - PersonIdent committerIdent = - identifiedUser.newCommitterIdent(TimeUtil.nowTs(), - serverTimeZone); - - final ObjectId computedChangeId = - ChangeIdUtil - .computeChangeId(commitToCherryPick.getTree(), mergeTip, - commitToCherryPick.getAuthorIdent(), committerIdent, message); - String commitMessage = - ChangeIdUtil.insertId(message, computedChangeId).trim() + '\n'; - - RevCommit cherryPickCommit; - ObjectInserter oi = git.newObjectInserter(); - try { - ProjectState projectState = refControl.getProjectControl().getProjectState(); - cherryPickCommit = - mergeUtilFactory.create(projectState).createCherryPickFromCommit(git, oi, mergeTip, - commitToCherryPick, committerIdent, commitMessage, revWalk); - } catch (MergeIdenticalTreeException | MergeConflictException e) { - throw new MergeException("Cherry pick failed: " + e.getMessage()); - } finally { - oi.release(); - } - - Change.Key changeKey; - final List<String> idList = cherryPickCommit.getFooterLines( - FooterConstants.CHANGE_ID); - if (!idList.isEmpty()) { - final String idStr = idList.get(idList.size() - 1).trim(); - changeKey = new Change.Key(idStr); - } else { - changeKey = new Change.Key("I" + computedChangeId.name()); - } - - Branch.NameKey newDest = - new Branch.NameKey(change.getProject(), destRef.getName()); - List<ChangeData> destChanges = queryProvider.get() - .setLimit(2) - .byBranchKey(newDest, changeKey); - if (destChanges.size() > 1) { - throw new InvalidChangeOperationException("Several changes with key " - + changeKey + " reside on the same branch. " - + "Cannot create a new patch set."); - } else if (destChanges.size() == 1) { - // The change key exists on the destination branch. The cherry pick - // will be added as a new patch set. - return insertPatchSet(git, revWalk, destChanges.get(0).change(), - cherryPickCommit, refControl, identifiedUser); - } else { - // Change key not found on destination branch. We can create a new - // change. - Change newChange = createNewChange(git, revWalk, changeKey, project, - destRef, cherryPickCommit, refControl, - identifiedUser, change.getTopic()); - - addMessageToSourceChange(change, patch.getId(), destinationBranch, - cherryPickCommit, identifiedUser, refControl); - - addMessageToDestinationChange(newChange, change.getDest().getShortName(), - identifiedUser, refControl); - - return newChange.getId(); - } - } finally { - revWalk.release(); - } - } finally { - git.close(); - } } private Change.Id insertPatchSet(Repository git, RevWalk revWalk, Change change,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ConsistencyChecker.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ConsistencyChecker.java index ad1e160..ee28ed2 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ConsistencyChecker.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ConsistencyChecker.java
@@ -153,7 +153,7 @@ return Result.create(c, problems); } finally { if (rw != null) { - rw.release(); + rw.close(); } if (repo != null) { repo.close();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java index 1855202..4dffd67 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java
@@ -158,71 +158,63 @@ } Project.NameKey project = rsrc.getNameKey(); - Repository git = gitManager.openRepository(project); - - try { - RevWalk rw = new RevWalk(git); - try { - ObjectId parentCommit; - if (input.baseChange != null) { - List<Change> changes = changeUtil.findChanges(input.baseChange); - if (changes.size() != 1) { - throw new InvalidChangeOperationException( - "Base change not found: " + input.baseChange); - } - Change change = Iterables.getOnlyElement(changes); - if (!rsrc.getControl().controlFor(change).isVisible(db.get())) { - throw new InvalidChangeOperationException( - "Base change not found: " + input.baseChange); - } - PatchSet ps = db.get().patchSets().get( - new PatchSet.Id(change.getId(), - change.currentPatchSetId().get())); - parentCommit = ObjectId.fromString(ps.getRevision().get()); - } else { - Ref destRef = git.getRef(refName); - if (destRef == null) { - throw new UnprocessableEntityException(String.format( - "Branch %s does not exist.", refName)); - } - parentCommit = destRef.getObjectId(); + try (Repository git = gitManager.openRepository(project); + RevWalk rw = new RevWalk(git)) { + ObjectId parentCommit; + if (input.baseChange != null) { + List<Change> changes = changeUtil.findChanges(input.baseChange); + if (changes.size() != 1) { + throw new InvalidChangeOperationException( + "Base change not found: " + input.baseChange); } - RevCommit mergeTip = rw.parseCommit(parentCommit); - - Timestamp now = TimeUtil.nowTs(); - IdentifiedUser me = (IdentifiedUser) userProvider.get(); - PersonIdent author = me.newCommitterIdent(now, serverTimeZone); - - ObjectId id = ChangeIdUtil.computeChangeId(mergeTip.getTree(), - mergeTip, author, author, input.subject); - String commitMessage = ChangeIdUtil.insertId(input.subject, id); - - RevCommit c = newCommit(git, rw, author, mergeTip, commitMessage); - - Change change = new Change( - getChangeId(id, c), - new Change.Id(db.get().nextChangeId()), - me.getAccountId(), - new Branch.NameKey(project, refName), - now); - - ChangeInserter ins = - changeInserterFactory.create(refControl.getProjectControl(), - change, c); - - validateCommit(git, refControl, c, me, ins); - updateRef(git, rw, c, change, ins.getPatchSet()); - - change.setTopic(input.topic); - ins.setDraft(input.status != null && input.status == ChangeStatus.DRAFT); - ins.insert(); - - return Response.created(json.format(change.getId())); - } finally { - rw.release(); + Change change = Iterables.getOnlyElement(changes); + if (!rsrc.getControl().controlFor(change).isVisible(db.get())) { + throw new InvalidChangeOperationException( + "Base change not found: " + input.baseChange); + } + PatchSet ps = db.get().patchSets().get( + new PatchSet.Id(change.getId(), + change.currentPatchSetId().get())); + parentCommit = ObjectId.fromString(ps.getRevision().get()); + } else { + Ref destRef = git.getRef(refName); + if (destRef == null) { + throw new UnprocessableEntityException(String.format( + "Branch %s does not exist.", refName)); + } + parentCommit = destRef.getObjectId(); } - } finally { - git.close(); + RevCommit mergeTip = rw.parseCommit(parentCommit); + + Timestamp now = TimeUtil.nowTs(); + IdentifiedUser me = (IdentifiedUser) userProvider.get(); + PersonIdent author = me.newCommitterIdent(now, serverTimeZone); + + ObjectId id = ChangeIdUtil.computeChangeId(mergeTip.getTree(), + mergeTip, author, author, input.subject); + String commitMessage = ChangeIdUtil.insertId(input.subject, id); + + RevCommit c = newCommit(git, rw, author, mergeTip, commitMessage); + + Change change = new Change( + getChangeId(id, c), + new Change.Id(db.get().nextChangeId()), + me.getAccountId(), + new Branch.NameKey(project, refName), + now); + + ChangeInserter ins = + changeInserterFactory.create(refControl.getProjectControl(), + change, c); + + validateCommit(git, refControl, c, me, ins); + updateRef(git, rw, c, change, ins.getPatchSet()); + + change.setTopic(input.topic); + ins.setDraft(input.status != null && input.status == ChangeStatus.DRAFT); + ins.insert(); + + return Response.created(json.format(change.getId())); } } @@ -275,8 +267,7 @@ PersonIdent authorIdent, RevCommit mergeTip, String commitMessage) throws IOException { RevCommit emptyCommit; - ObjectInserter oi = git.newObjectInserter(); - try { + try (ObjectInserter oi = git.newObjectInserter()) { CommitBuilder commit = new CommitBuilder(); commit.setTreeId(mergeTip.getTree().getId()); commit.setParentId(mergeTip); @@ -284,8 +275,6 @@ commit.setCommitter(authorIdent); commit.setMessage(commitMessage); emptyCommit = rw.parseCommit(insert(oi, commit)); - } finally { - oi.release(); } return emptyCommit; }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java index 5335cb9..a8e1793 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/FileContentUtil.java
@@ -58,64 +58,57 @@ public BinaryResult getContent(ProjectState project, ObjectId revstr, String path) throws ResourceNotFoundException, IOException { - Repository repo = openRepository(project); - try { - RevWalk rw = new RevWalk(repo); - try { - RevCommit commit = rw.parseCommit(revstr); - ObjectReader reader = rw.getObjectReader(); - TreeWalk tw = TreeWalk.forPath(reader, path, commit.getTree()); - if (tw == null) { - throw new ResourceNotFoundException(); - } - - org.eclipse.jgit.lib.FileMode mode = tw.getFileMode(0); - ObjectId id = tw.getObjectId(0); - if (mode == org.eclipse.jgit.lib.FileMode.GITLINK) { - return BinaryResult.create(id.name()) - .setContentType(X_GIT_GITLINK) - .base64(); - } - - final ObjectLoader obj = repo.open(id, OBJ_BLOB); - byte[] raw; - try { - raw = obj.getCachedBytes(MAX_SIZE); - } catch (LargeObjectException e) { - raw = null; - } - - BinaryResult result; - if (raw != null) { - result = BinaryResult.create(raw); - } else { - result = asBinaryResult(obj); - } - - String type; - if (mode == org.eclipse.jgit.lib.FileMode.SYMLINK) { - type = X_GIT_SYMLINK; - } else { - type = registry.getMimeType(path, raw).toString(); - type = resolveContentType(project, path, FileMode.FILE, type); - } - return result.setContentType(type).base64(); - } finally { - rw.release(); + try (Repository repo = openRepository(project); + RevWalk rw = new RevWalk(repo)) { + RevCommit commit = rw.parseCommit(revstr); + ObjectReader reader = rw.getObjectReader(); + TreeWalk tw = TreeWalk.forPath(reader, path, commit.getTree()); + if (tw == null) { + throw new ResourceNotFoundException(); } - } finally { - repo.close(); + + org.eclipse.jgit.lib.FileMode mode = tw.getFileMode(0); + ObjectId id = tw.getObjectId(0); + if (mode == org.eclipse.jgit.lib.FileMode.GITLINK) { + return BinaryResult.create(id.name()) + .setContentType(X_GIT_GITLINK) + .base64(); + } + + final ObjectLoader obj = repo.open(id, OBJ_BLOB); + byte[] raw; + try { + raw = obj.getCachedBytes(MAX_SIZE); + } catch (LargeObjectException e) { + raw = null; + } + + BinaryResult result; + if (raw != null) { + result = BinaryResult.create(raw); + } else { + result = asBinaryResult(obj); + } + + String type; + if (mode == org.eclipse.jgit.lib.FileMode.SYMLINK) { + type = X_GIT_SYMLINK; + } else { + type = registry.getMimeType(path, raw).toString(); + type = resolveContentType(project, path, FileMode.FILE, type); + } + return result.setContentType(type).base64(); } } private static BinaryResult asBinaryResult(final ObjectLoader obj) { - @SuppressWarnings("resource") BinaryResult result = new BinaryResult() { @Override public void writeTo(OutputStream os) throws IOException { obj.copyTo(os); } - }.setContentLength(obj.getSize()); + }; + result.setContentLength(obj.getSize()); return result; }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java index 1c0b0a4..e19b6a9 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java
@@ -31,6 +31,7 @@ import com.google.gerrit.reviewdb.client.AccountPatchReview; import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.IdentifiedUser; @@ -178,30 +179,24 @@ private List<String> query(RevisionResource resource) throws RepositoryNotFoundException, IOException { - Repository git = - gitManager.openRepository(resource.getChange().getProject()); - try { - TreeWalk tw = new TreeWalk(git); - try { - RevCommit c = new RevWalk(tw.getObjectReader()) - .parseCommit(ObjectId.fromString( - resource.getPatchSet().getRevision().get())); + Project.NameKey project = resource.getChange().getProject(); + try (Repository git = gitManager.openRepository(project); + ObjectReader or = git.newObjectReader(); + RevWalk rw = new RevWalk(or); + TreeWalk tw = new TreeWalk(or)) { + RevCommit c = rw.parseCommit( + ObjectId.fromString(resource.getPatchSet().getRevision().get())); - tw.addTree(c.getTree()); - tw.setRecursive(true); - List<String> paths = new ArrayList<>(); - while (tw.next() && paths.size() < 20) { - String s = tw.getPathString(); - if (s.contains(query)) { - paths.add(s); - } + tw.addTree(c.getTree()); + tw.setRecursive(true); + List<String> paths = new ArrayList<>(); + while (tw.next() && paths.size() < 20) { + String s = tw.getPathString(); + if (s.contains(query)) { + paths.add(s); } - return paths; - } finally { - tw.release(); } - } finally { - git.close(); + return paths; } } @@ -261,76 +256,69 @@ private List<String> copy(Set<String> paths, PatchSet.Id old, RevisionResource resource, Account.Id userId) throws IOException, PatchListNotAvailableException, OrmException { - Repository git = - gitManager.openRepository(resource.getChange().getProject()); - try { - ObjectReader reader = git.newObjectReader(); - try { - PatchList oldList = patchListCache.get( - resource.getChange(), - db.get().patchSets().get(old)); - - PatchList curList = patchListCache.get( - resource.getChange(), - resource.getPatchSet()); - - int sz = paths.size(); - List<AccountPatchReview> inserts = Lists.newArrayListWithCapacity(sz); - List<String> pathList = Lists.newArrayListWithCapacity(sz); - + Project.NameKey project = resource.getChange().getProject(); + try (Repository git = gitManager.openRepository(project); + ObjectReader reader = git.newObjectReader(); RevWalk rw = new RevWalk(reader); - TreeWalk tw = new TreeWalk(reader); - tw.setFilter(PathFilterGroup.createFromStrings(paths)); - tw.setRecursive(true); - int o = tw.addTree(rw.parseCommit(oldList.getNewId()).getTree()); - int c = tw.addTree(rw.parseCommit(curList.getNewId()).getTree()); + TreeWalk tw = new TreeWalk(reader)) { + PatchList oldList = patchListCache.get( + resource.getChange(), + db.get().patchSets().get(old)); - int op = -1; - if (oldList.getOldId() != null) { - op = tw.addTree(rw.parseTree(oldList.getOldId())); - } + PatchList curList = patchListCache.get( + resource.getChange(), + resource.getPatchSet()); - int cp = -1; - if (curList.getOldId() != null) { - cp = tw.addTree(rw.parseTree(curList.getOldId())); - } + int sz = paths.size(); + List<AccountPatchReview> inserts = Lists.newArrayListWithCapacity(sz); + List<String> pathList = Lists.newArrayListWithCapacity(sz); - while (tw.next()) { - String path = tw.getPathString(); - if (tw.getRawMode(o) != 0 && tw.getRawMode(c) != 0 - && tw.idEqual(o, c) - && paths.contains(path)) { - // File exists in previously reviewed oldList and in curList. - // File content is identical. - inserts.add(new AccountPatchReview( - new Patch.Key( - resource.getPatchSet().getId(), - path), - userId)); - pathList.add(path); - } else if (op >= 0 && cp >= 0 - && tw.getRawMode(o) == 0 && tw.getRawMode(c) == 0 - && tw.getRawMode(op) != 0 && tw.getRawMode(cp) != 0 - && tw.idEqual(op, cp) - && paths.contains(path)) { - // File was deleted in previously reviewed oldList and curList. - // File exists in ancestor of oldList and curList. - // File content is identical in ancestors. - inserts.add(new AccountPatchReview( - new Patch.Key( - resource.getPatchSet().getId(), - path), - userId)); - pathList.add(path); - } - } - db.get().accountPatchReviews().insert(inserts); - return pathList; - } finally { - reader.release(); + tw.setFilter(PathFilterGroup.createFromStrings(paths)); + tw.setRecursive(true); + int o = tw.addTree(rw.parseCommit(oldList.getNewId()).getTree()); + int c = tw.addTree(rw.parseCommit(curList.getNewId()).getTree()); + + int op = -1; + if (oldList.getOldId() != null) { + op = tw.addTree(rw.parseTree(oldList.getOldId())); } - } finally { - git.close(); + + int cp = -1; + if (curList.getOldId() != null) { + cp = tw.addTree(rw.parseTree(curList.getOldId())); + } + + while (tw.next()) { + String path = tw.getPathString(); + if (tw.getRawMode(o) != 0 && tw.getRawMode(c) != 0 + && tw.idEqual(o, c) + && paths.contains(path)) { + // File exists in previously reviewed oldList and in curList. + // File content is identical. + inserts.add(new AccountPatchReview( + new Patch.Key( + resource.getPatchSet().getId(), + path), + userId)); + pathList.add(path); + } else if (op >= 0 && cp >= 0 + && tw.getRawMode(o) == 0 && tw.getRawMode(c) == 0 + && tw.getRawMode(op) != 0 && tw.getRawMode(cp) != 0 + && tw.idEqual(op, cp) + && paths.contains(path)) { + // File was deleted in previously reviewed oldList and curList. + // File exists in ancestor of oldList and curList. + // File content is identical in ancestors. + inserts.add(new AccountPatchReview( + new Patch.Key( + resource.getPatchSet().getId(), + path), + userId)); + pathList.add(path); + } + } + db.get().accountPatchReviews().insert(inserts); + return pathList; } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetArchive.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetArchive.java index d602c47..913f69e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetArchive.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetArchive.java
@@ -126,7 +126,7 @@ @Override public void close() throws IOException { - rw.release(); + rw.close(); repo.close(); } }; @@ -139,7 +139,7 @@ return bin; } finally { if (close) { - rw.release(); + rw.close(); } } } finally {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetPatch.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetPatch.java index 4a8be84..afd1156 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetPatch.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetPatch.java
@@ -94,15 +94,16 @@ private void format(OutputStream out) throws IOException { out.write(formatEmailHeader(commit).getBytes(UTF_8)); - DiffFormatter fmt = new DiffFormatter(out); - fmt.setRepository(repo); - fmt.format(base.getTree(), commit.getTree()); - fmt.flush(); + try (DiffFormatter fmt = new DiffFormatter(out)) { + fmt.setRepository(repo); + fmt.format(base.getTree(), commit.getTree()); + fmt.flush(); + } } @Override public void close() throws IOException { - rw.release(); + rw.close(); repo.close(); } }; @@ -123,7 +124,7 @@ return bin; } finally { if (close) { - rw.release(); + rw.close(); } } } finally {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java index f58a2a0..8c01403 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java
@@ -80,19 +80,12 @@ @Override public RelatedInfo apply(RevisionResource rsrc) throws RepositoryNotFoundException, IOException, OrmException { - Repository git = gitMgr.openRepository(rsrc.getChange().getProject()); - try { + try (Repository git = gitMgr.openRepository(rsrc.getChange().getProject()); + RevWalk rw = new RevWalk(git)) { Ref ref = git.getRef(rsrc.getChange().getDest().get()); - RevWalk rw = new RevWalk(git); - try { - RelatedInfo info = new RelatedInfo(); - info.changes = walk(rsrc, rw, ref); - return info; - } finally { - rw.release(); - } - } finally { - git.close(); + RelatedInfo info = new RelatedInfo(); + info.changes = walk(rsrc, rw, ref); + return info; } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRevisionActions.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRevisionActions.java index d58c8d2..b21bee2 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRevisionActions.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRevisionActions.java
@@ -14,22 +14,59 @@ package com.google.gerrit.server.change; +import com.google.common.base.Strings; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; +import com.google.gerrit.extensions.restapi.ETagView; import com.google.gerrit.extensions.restapi.Response; -import com.google.gerrit.extensions.restapi.RestReadView; +import com.google.gerrit.server.CurrentUser; +import com.google.gerrit.server.config.GerritServerConfig; +import com.google.gerrit.server.query.change.ChangeData; +import com.google.gerrit.server.query.change.InternalChangeQuery; +import com.google.gwtorm.server.OrmException; +import com.google.gwtorm.server.OrmRuntimeException; import com.google.inject.Inject; +import com.google.inject.Provider; import com.google.inject.Singleton; -@Singleton -public class GetRevisionActions implements RestReadView<RevisionResource> { - private final ActionJson delegate; +import org.eclipse.jgit.lib.Config; +@Singleton +public class GetRevisionActions implements ETagView<RevisionResource> { + private final ActionJson delegate; + private final Provider<InternalChangeQuery> queryProvider; + private final Config config; @Inject - GetRevisionActions(ActionJson delegate) { + GetRevisionActions( + ActionJson delegate, + Provider<InternalChangeQuery> queryProvider, + @GerritServerConfig Config config) { this.delegate = delegate; + this.queryProvider = queryProvider; + this.config = config; } @Override public Object apply(RevisionResource rsrc) { return Response.withMustRevalidate(delegate.format(rsrc)); } + + @Override + public String getETag(RevisionResource rsrc) { + String topic = rsrc.getChange().getTopic(); + if (!Submit.wholeTopicEnabled(config) + || Strings.isNullOrEmpty(topic)) { + return rsrc.getETag(); + } + Hasher h = Hashing.md5().newHasher(); + CurrentUser user = rsrc.getControl().getCurrentUser(); + try { + for (ChangeData c : queryProvider.get().byTopicOpen(topic)) { + new ChangeResource(c.changeControl()).prepareETag(h, user); + } + } catch (OrmException e){ + throw new OrmRuntimeException(e); + } + return h.hash().toString(); + } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java index e0cdebb..7e9bb14 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java
@@ -19,6 +19,7 @@ import com.google.gerrit.extensions.restapi.ResourceConflictException; import com.google.gerrit.extensions.restapi.RestReadView; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.project.ChangeControl; @@ -55,26 +56,19 @@ ChangeControl ctl = rsrc.getControl(); PatchSet ps = db.get().patchSets().get(ctl.getChange().currentPatchSetId()); - Repository r = - repoManager.openRepository(ctl.getProject().getNameKey()); - try { - RevWalk rw = new RevWalk(r); + Project.NameKey project = ctl.getProject().getNameKey(); + try (Repository r = repoManager.openRepository(project); + RevWalk rw = new RevWalk(r)) { + rw.setRetainBody(false); + RevCommit rev; try { - rw.setRetainBody(false); - RevCommit rev; - try { - rev = rw.parseCommit(ObjectId.fromString(ps.getRevision().get())); - } catch (IncorrectObjectTypeException err) { - throw new BadRequestException(err.getMessage()); - } catch (MissingObjectException err) { - throw new ResourceConflictException(err.getMessage()); - } - return new IncludedInInfo(IncludedInResolver.resolve(r, rw, rev)); - } finally { - rw.release(); + rev = rw.parseCommit(ObjectId.fromString(ps.getRevision().get())); + } catch (IncorrectObjectTypeException err) { + throw new BadRequestException(err.getMessage()); + } catch (MissingObjectException err) { + throw new ResourceConflictException(err.getMessage()); } - } finally { - r.close(); + return new IncludedInInfo(IncludedInResolver.resolve(r, rw, rev)); } } @@ -87,4 +81,4 @@ tags = in.getTags(); } } -} \ No newline at end of file +}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java index 5f1ed5b..d6b6ab8 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java
@@ -225,8 +225,7 @@ } try { Map<String, Ref> refs = key.load.repo.getAllRefs(); - RevWalk rw = CodeReviewCommit.newRevWalk(key.load.repo); - try { + try (RevWalk rw = CodeReviewCommit.newRevWalk(key.load.repo)) { RevFlag canMerge = rw.newFlag("CAN_MERGE"); CodeReviewCommit rev = parse(rw, key.commit); rev.add(canMerge); @@ -243,8 +242,6 @@ canMerge, accepted, key.load.dest).dryRun(tip, rev); - } finally { - rw.release(); } } finally { key.load = null;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Rebase.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Rebase.java index 3f61b01..b0392f7 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Rebase.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Rebase.java
@@ -184,6 +184,7 @@ .setLabel("Rebase") .setTitle("Rebase onto tip of branch or parent change") .setVisible(resource.getChange().getStatus().isOpen() + && resource.isCurrent() && resource.getControl().canRebase() && hasOneParent(resource.getPatchSet().getId())); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/RevisionResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/RevisionResource.java index e58d1a1..a18df5b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/RevisionResource.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/RevisionResource.java
@@ -104,4 +104,8 @@ } return s; } + + public boolean isCurrent() { + return ps.getId().equals(getChange().currentPatchSetId()); + } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java index 41151ae..5fae929 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
@@ -169,7 +169,7 @@ this.titlePattern = new ParameterizedString(MoreObjects.firstNonNull( cfg.getString("change", null, "submitTooltip"), DEFAULT_TOOLTIP)); - submitWholeTopic = cfg.getBoolean("change", null, "submitWholeTopic" , false); + submitWholeTopic = wholeTopicEnabled(cfg); this.submitTopicLabel = MoreObjects.firstNonNull( Strings.emptyToNull(cfg.getString("change", null, "submitTopicLabel")), "Submit whole topic"); @@ -206,17 +206,19 @@ rsrc.getPatchSet().getRevision().get())); } - change = submit(rsrc, caller, false); - if (change == null) { - throw new ResourceConflictException("change is " - + status(dbProvider.get().changes().get(rsrc.getChange().getId()))); - } + List<Change> submittedChanges = submit(rsrc, caller, false); if (input.waitForMerge) { - mergeQueue.merge(change.getDest()); + for (Change c : submittedChanges) { + // TODO(sbeller): We should make schedule return a Future, then we + // could do these all in parallel and still block until they're done. + mergeQueue.merge(c.getDest()); + } change = dbProvider.get().changes().get(change.getId()); } else { - mergeQueue.schedule(change.getDest()); + for (Change c : submittedChanges) { + mergeQueue.schedule(c.getDest()); + } } if (change == null) { @@ -288,13 +290,13 @@ .setTitle("") .setVisible(false); } + List<ChangeData> changesByTopic = null; if (submitWholeTopic && !Strings.isNullOrEmpty(topic)) { - List<ChangeData> changesByTopic = null; - try { - changesByTopic = queryProvider.get().byTopicOpen(topic); - } catch (OrmException e) { - throw new OrmRuntimeException(e); - } + changesByTopic = getChangesByTopic(topic); + } + if (submitWholeTopic + && !Strings.isNullOrEmpty(topic) + && changesByTopic.size() > 1) { Map<String, String> params = ImmutableMap.of( "topicSize", String.valueOf(changesByTopic.size())); String topicProblems = problemsForSubmittingChanges(changesByTopic, @@ -345,9 +347,10 @@ .orNull(); } - private Change submitToDatabase(ReviewDb db, Change.Id changeId, - final Timestamp timestamp) throws OrmException { - return db.changes().atomicUpdate(changeId, + private Change submitToDatabase(final ReviewDb db, final Change.Id changeId, + final Timestamp timestamp) throws OrmException, + ResourceConflictException { + Change ret = db.changes().atomicUpdate(changeId, new AtomicUpdate<Change>() { @Override public Change update(Change change) { @@ -359,6 +362,12 @@ return null; } }); + if (ret != null) { + return ret; + } else { + throw new ResourceConflictException("change " + changeId + " is " + + status(db.changes().get(changeId))); + } } private Change submitThisChange(RevisionResource rsrc, IdentifiedUser caller, @@ -376,13 +385,11 @@ db.changes().beginTransaction(change.getId()); try { - BatchMetaDataUpdate batch = approve(rsrc, update, caller, timestamp); + BatchMetaDataUpdate batch = approve(rsrc.getPatchSet().getId(), + cd.changeControl(), update, caller, timestamp); // Write update commit after all normalized label commits. batch.write(update, new CommitBuilder()); change = submitToDatabase(db, change.getId(), timestamp); - if (change == null) { - return null; - } db.commit(); } finally { db.rollback(); @@ -391,7 +398,7 @@ return change; } - private Change submitWholeTopic(RevisionResource rsrc, IdentifiedUser caller, + private List<Change> submitWholeTopic(RevisionResource rsrc, IdentifiedUser caller, boolean force, String topic) throws ResourceConflictException, OrmException, IOException { Preconditions.checkNotNull(topic); @@ -415,45 +422,45 @@ db.changes().beginTransaction(change.getId()); try { - BatchMetaDataUpdate batch = approve(rsrc, update, caller, timestamp); - // Write update commit after all normalized label commits. - batch.write(update, new CommitBuilder()); - for (ChangeData c : changesByTopic) { - if (submitToDatabase(db, c.getId(), timestamp) == null) { - return null; - } + BatchMetaDataUpdate batch = approve(c.currentPatchSet().getId(), + c.changeControl(), update, caller, timestamp); + // Write update commit after all normalized label commits. + batch.write(update, new CommitBuilder()); + submitToDatabase(db, c.getId(), timestamp); } db.commit(); } finally { db.rollback(); } List<Change.Id> ids = new ArrayList<>(changesByTopic.size()); + List<Change> ret = new ArrayList<>(changesByTopic.size()); for (ChangeData c : changesByTopic) { ids.add(c.getId()); + ret.add(c.change()); } indexer.indexAsync(ids).checkedGet(); - return change; + + return ret; } - public Change submit(RevisionResource rsrc, IdentifiedUser caller, + public List<Change> submit(RevisionResource rsrc, IdentifiedUser caller, boolean force) throws ResourceConflictException, OrmException, IOException { String topic = rsrc.getChange().getTopic(); if (submitWholeTopic && !Strings.isNullOrEmpty(topic)) { return submitWholeTopic(rsrc, caller, force, topic); } else { - return submitThisChange(rsrc, caller, force); + return Arrays.asList(submitThisChange(rsrc, caller, force)); } } - private BatchMetaDataUpdate approve(RevisionResource rsrc, + private BatchMetaDataUpdate approve(PatchSet.Id psId, ChangeControl control, ChangeUpdate update, IdentifiedUser caller, Timestamp timestamp) throws OrmException { - PatchSet.Id psId = rsrc.getPatchSet().getId(); Map<PatchSetApproval.Key, PatchSetApproval> byKey = Maps.newHashMap(); for (PatchSetApproval psa : - approvalsUtil.byPatchSet(dbProvider.get(), rsrc.getControl(), psId)) { + approvalsUtil.byPatchSet(dbProvider.get(), control, psId)) { if (!byKey.containsKey(psa.getKey())) { byKey.put(psa.getKey(), psa); } @@ -464,7 +471,7 @@ || !submit.getAccountId().equals(caller.getAccountId())) { submit = new PatchSetApproval( new PatchSetApproval.Key( - rsrc.getPatchSet().getId(), + psId, caller.getAccountId(), LabelId.SUBMIT), (short) 1, TimeUtil.nowTs()); @@ -479,7 +486,7 @@ // 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(rsrc.getControl(), byKey.values()); + labelNormalizer.normalize(control, byKey.values()); // TODO(dborowitz): Don't use a label in notedb; just check when status // change happened. @@ -489,13 +496,13 @@ dbProvider.get().patchSetApprovals().delete(normalized.deleted()); try { - return saveToBatch(rsrc, update, normalized, timestamp); + return saveToBatch(control, update, normalized, timestamp); } catch (IOException e) { throw new OrmException(e); } } - private BatchMetaDataUpdate saveToBatch(RevisionResource rsrc, + private BatchMetaDataUpdate saveToBatch(ChangeControl ctl, ChangeUpdate callerUpdate, LabelNormalizer.Result normalized, Timestamp timestamp) throws IOException { Table<Account.Id, String, Optional<Short>> byUser = HashBasedTable.create(); @@ -507,7 +514,6 @@ byUser.put(psa.getAccountId(), psa.getLabel(), Optional.<Short> absent()); } - ChangeControl ctl = rsrc.getControl(); BatchMetaDataUpdate batch = callerUpdate.openUpdate(); for (Account.Id accountId : byUser.rowKeySet()) { if (!accountId.equals(callerUpdate.getUser().getAccountId())) { @@ -654,6 +660,18 @@ return new RevisionResource(changes.parse(target), rsrc.getPatchSet()); } + static boolean wholeTopicEnabled(Config config) { + return config.getBoolean("change", null, "submitWholeTopic" , false); + } + + private List<ChangeData> getChangesByTopic(String topic) { + try { + return queryProvider.get().byTopicOpen(topic); + } catch (OrmException e) { + throw new OrmRuntimeException(e); + } + } + public static class CurrentRevision implements RestModifyView<ChangeResource, SubmitInput> { private final Provider<ReviewDb> dbProvider;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RebaseChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RebaseChange.java index f80a474..6b49206 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RebaseChange.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RebaseChange.java
@@ -119,14 +119,9 @@ "Cannot rebase: New patch sets are not allowed to be added to change: " + changeId.toString()); } - Repository git = null; - RevWalk rw = null; - ObjectInserter inserter = null; - try { - git = gitManager.openRepository(change.getProject()); - rw = new RevWalk(git); - inserter = git.newObjectInserter(); - + try (Repository git = gitManager.openRepository(change.getProject()); + RevWalk rw = new RevWalk(git); + ObjectInserter inserter = git.newObjectInserter()) { String baseRev = newBaseRev; if (baseRev == null) { baseRev = findBaseRevision(patchSetId, db.get(), @@ -149,16 +144,6 @@ committerIdent, true, ValidatePolicy.GERRIT); } catch (MergeConflictException e) { throw new IOException(e.getMessage()); - } finally { - if (inserter != null) { - inserter.release(); - } - if (rw != null) { - rw.release(); - } - if (git != null) { - git.close(); - } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritServerConfigProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritServerConfigProvider.java index aa699c5..4b1236b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritServerConfigProvider.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritServerConfigProvider.java
@@ -44,10 +44,11 @@ @Override public Config get() { - FileBasedConfig cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED); + FileBasedConfig cfg = + new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED); if (!cfg.getFile().exists()) { - log.info("No " + site.gerrit_config.getAbsolutePath() + log.info("No " + site.gerrit_config.toAbsolutePath() + "; assuming defaults"); return new GerritConfig(cfg, secureStore); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetSummary.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetSummary.java index 9aa8590..feac473 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GetSummary.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GetSummary.java
@@ -24,7 +24,6 @@ import org.eclipse.jgit.internal.storage.file.WindowCacheStatAccessor; import org.kohsuke.args4j.Option; -import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; @@ -33,6 +32,8 @@ import java.lang.management.ThreadMXBean; import java.net.InetAddress; import java.net.UnknownHostException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; @@ -43,7 +44,7 @@ public class GetSummary implements RestReadView<ConfigResource> { private final WorkQueue workQueue; - private final File sitePath; + private final Path sitePath; @Option(name = "--gc", usage = "perform Java GC before retrieving memory stats") private boolean gc; @@ -62,7 +63,7 @@ } @Inject - public GetSummary(WorkQueue workQueue, @SitePath File sitePath) { + public GetSummary(WorkQueue workQueue, @SitePath Path sitePath) { this.workQueue = workQueue; this.sitePath = sitePath; } @@ -186,7 +187,8 @@ } catch (UnknownHostException e) { } - jvmSummary.currentWorkingDirectory = path(new File(".").getAbsoluteFile().getParentFile()); + jvmSummary.currentWorkingDirectory = + path(Paths.get(".").toAbsolutePath().getParent()); jvmSummary.site = path(sitePath); return jvmSummary; } @@ -210,11 +212,11 @@ return String.format("%1$6.2f%2$s", value, suffix).trim(); } - private static String path(File file) { + private static String path(Path path) { try { - return file.getCanonicalPath(); + return path.toRealPath().normalize().toString(); } catch (IOException err) { - return file.getAbsolutePath(); + return path.toAbsolutePath().normalize().toString(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java index 76f5323..3754674 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/PluginConfigFactory.java
@@ -35,6 +35,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.Map; @Singleton @@ -61,7 +62,7 @@ this.projectStateFactory = projectStateFactory; this.pluginConfigs = Maps.newHashMap(); - this.cfgSnapshot = FileSnapshot.save(site.gerrit_config); + this.cfgSnapshot = FileSnapshot.save(site.gerrit_config.toFile()); this.cfg = cfgProvider.get(); } @@ -103,8 +104,9 @@ * @return the plugin configuration from the 'gerrit.config' file */ public PluginConfig getFromGerritConfig(String pluginName, boolean refresh) { - if (refresh && cfgSnapshot.isModified(site.gerrit_config)) { - cfgSnapshot = FileSnapshot.save(site.gerrit_config); + File configFile = site.gerrit_config.toFile(); + if (refresh && cfgSnapshot.isModified(configFile)) { + cfgSnapshot = FileSnapshot.save(configFile); cfg = cfgProvider.get(); } return new PluginConfig(pluginName, cfg); @@ -250,20 +252,21 @@ return pluginConfigs.get(pluginName); } - File pluginConfigFile = new File(site.etc_dir, pluginName + ".config"); - FileBasedConfig cfg = new FileBasedConfig(pluginConfigFile, FS.DETECTED); + Path pluginConfigFile = site.etc_dir.resolve(pluginName + ".config"); + FileBasedConfig cfg = + new FileBasedConfig(pluginConfigFile.toFile(), FS.DETECTED); pluginConfigs.put(pluginName, cfg); if (!cfg.getFile().exists()) { - log.info("No " + pluginConfigFile.getAbsolutePath() + "; assuming defaults"); + log.info("No " + pluginConfigFile.toAbsolutePath() + "; assuming defaults"); return cfg; } try { cfg.load(); } catch (IOException e) { - log.warn("Failed to load " + pluginConfigFile.getAbsolutePath(), e); + log.warn("Failed to load " + pluginConfigFile.toAbsolutePath(), e); } catch (ConfigInvalidException e) { - log.warn("Failed to load " + pluginConfigFile.getAbsolutePath(), e); + log.warn("Failed to load " + pluginConfigFile.toAbsolutePath(), e); } return cfg;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java index fbff7c4..a6a3e53 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java
@@ -14,12 +14,15 @@ package com.google.gerrit.server.config; +import com.google.common.collect.Iterables; import com.google.inject.Inject; import com.google.inject.Singleton; -import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; /** Important paths within a {@link SitePath}. */ @Singleton @@ -28,88 +31,84 @@ public static final String HEADER_FILENAME = "GerritSiteHeader.html"; public static final String FOOTER_FILENAME = "GerritSiteFooter.html"; - public final File site_path; - public final File bin_dir; - public final File etc_dir; - public final File lib_dir; - public final File tmp_dir; - public final File logs_dir; - public final File plugins_dir; - public final File data_dir; - public final File mail_dir; - public final File hooks_dir; - public final File static_dir; - public final File themes_dir; - public final File index_dir; + public final Path site_path; + public final Path bin_dir; + public final Path etc_dir; + public final Path lib_dir; + public final Path tmp_dir; + public final Path logs_dir; + public final Path plugins_dir; + public final Path data_dir; + public final Path mail_dir; + public final Path hooks_dir; + public final Path static_dir; + public final Path themes_dir; + public final Path index_dir; - public final File gerrit_sh; - public final File gerrit_war; + public final Path gerrit_sh; + public final Path gerrit_war; - public final File gerrit_config; - public final File secure_config; - public final File contact_information_pub; + public final Path gerrit_config; + public final Path secure_config; + public final Path contact_information_pub; - public final File ssl_keystore; - public final File ssh_key; - public final File ssh_rsa; - public final File ssh_dsa; - public final File peer_keys; + public final Path ssl_keystore; + public final Path ssh_key; + public final Path ssh_rsa; + public final Path ssh_dsa; + public final Path peer_keys; - public final File site_css; - public final File site_header; - public final File site_footer; - public final File site_gitweb; + public final Path site_css; + public final Path site_header; + public final Path site_footer; + public final Path site_gitweb; /** {@code true} if {@link #site_path} has not been initialized. */ public final boolean isNew; @Inject - public SitePaths(final @SitePath File sitePath) throws FileNotFoundException { + public SitePaths(@SitePath Path sitePath) throws IOException { site_path = sitePath; + Path p = sitePath; - bin_dir = new File(site_path, "bin"); - etc_dir = new File(site_path, "etc"); - lib_dir = new File(site_path, "lib"); - tmp_dir = new File(site_path, "tmp"); - plugins_dir = new File(site_path, "plugins"); - data_dir = new File(site_path, "data"); - logs_dir = new File(site_path, "logs"); - mail_dir = new File(etc_dir, "mail"); - hooks_dir = new File(site_path, "hooks"); - static_dir = new File(site_path, "static"); - themes_dir = new File(site_path, "themes"); - index_dir = new File(site_path, "index"); + bin_dir = p.resolve("bin"); + etc_dir = p.resolve("etc"); + lib_dir = p.resolve("lib"); + tmp_dir = p.resolve("tmp"); + plugins_dir = p.resolve("plugins"); + data_dir = p.resolve("data"); + logs_dir = p.resolve("logs"); + mail_dir = etc_dir.resolve("mail"); + hooks_dir = p.resolve("hooks"); + static_dir = p.resolve("static"); + themes_dir = p.resolve("themes"); + index_dir = p.resolve("index"); - gerrit_sh = new File(bin_dir, "gerrit.sh"); - gerrit_war = new File(bin_dir, "gerrit.war"); + gerrit_sh = bin_dir.resolve("gerrit.sh"); + gerrit_war = bin_dir.resolve("gerrit.war"); - gerrit_config = new File(etc_dir, "gerrit.config"); - secure_config = new File(etc_dir, "secure.config"); - contact_information_pub = new File(etc_dir, "contact_information.pub"); + gerrit_config = etc_dir.resolve("gerrit.config"); + secure_config = etc_dir.resolve("secure.config"); + contact_information_pub = etc_dir.resolve("contact_information.pub"); - ssl_keystore = new File(etc_dir, "keystore"); - ssh_key = new File(etc_dir, "ssh_host_key"); - ssh_rsa = new File(etc_dir, "ssh_host_rsa_key"); - ssh_dsa = new File(etc_dir, "ssh_host_dsa_key"); - peer_keys = new File(etc_dir, "peer_keys"); + ssl_keystore = etc_dir.resolve("keystore"); + ssh_key = etc_dir.resolve("ssh_host_key"); + ssh_rsa = etc_dir.resolve("ssh_host_rsa_key"); + ssh_dsa = etc_dir.resolve("ssh_host_dsa_key"); + peer_keys = etc_dir.resolve("peer_keys"); - site_css = new File(etc_dir, CSS_FILENAME); - site_header = new File(etc_dir, HEADER_FILENAME); - site_footer = new File(etc_dir, FOOTER_FILENAME); - site_gitweb = new File(etc_dir, "gitweb_config.perl"); + site_css = etc_dir.resolve(CSS_FILENAME); + site_header = etc_dir.resolve(HEADER_FILENAME); + site_footer = etc_dir.resolve(FOOTER_FILENAME); + site_gitweb = etc_dir.resolve("gitweb_config.perl"); - if (site_path.exists()) { - final String[] contents = site_path.list(); - if (contents != null) { - isNew = contents.length == 0; - } else if (site_path.isDirectory()) { - throw new FileNotFoundException("Cannot access " + site_path); - } else { - throw new FileNotFoundException("Not a directory: " + site_path); - } - } else { + boolean isNew; + try (DirectoryStream<Path> files = Files.newDirectoryStream(site_path)) { + isNew = Iterables.isEmpty(files); + } catch (NoSuchFileException e) { isNew = true; } + this.isNew = isNew; } /** @@ -120,16 +119,13 @@ * @param path the path string to resolve. May be null. * @return the resolved path; null if {@code path} was null or empty. */ - public File resolve(final String path) { + public Path resolve(String path) { if (path != null && !path.isEmpty()) { - File loc = new File(path); - if (!loc.isAbsolute()) { - loc = new File(site_path, path); - } + Path loc = site_path.resolve(path).normalize(); try { - return loc.getCanonicalFile(); + return loc.toRealPath(); } catch (IOException e) { - return loc.getAbsoluteFile(); + return loc.toAbsolutePath(); } } return null;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreModule.java index 6b195de..f6e08b8 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreModule.java
@@ -28,11 +28,12 @@ import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.util.StringUtils; -import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; import java.security.Security; /** Creates the {@link ContactStore} based on the configuration. */ @@ -46,7 +47,7 @@ public ContactStore provideContactStore(@GerritServerConfig final Config config, final SitePaths site, final SchemaFactory<ReviewDb> schema, final ContactStoreConnection.Factory connFactory) { - final String url = config.getString("contactstore", null, "url"); + String url = config.getString("contactstore", null, "url"); if (StringUtils.isEmptyOrNull(url)) { return new NoContactStore(); } @@ -56,18 +57,18 @@ + " needed to encrypt contact information"); } - final URL storeUrl; + URL storeUrl; try { storeUrl = new URL(url); } catch (MalformedURLException e) { throw new ProvisionException("Invalid contactstore.url: " + url, e); } - final String storeAPPSEC = config.getString("contactstore", null, "appsec"); - final File pubkey = site.contact_information_pub; - if (!pubkey.exists()) { + String storeAPPSEC = config.getString("contactstore", null, "appsec"); + Path pubkey = site.contact_information_pub; + if (!Files.exists(pubkey)) { throw new ProvisionException("PGP public key file \"" - + pubkey.getAbsolutePath() + "\" not found"); + + pubkey.toAbsolutePath() + "\" not found"); } return new EncryptedContactStore(storeUrl, storeAPPSEC, pubkey, schema, connFactory);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java b/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java index d8dbfed..e27f63d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java
@@ -42,12 +42,12 @@ import org.slf4j.LoggerFactory; import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; @@ -72,7 +72,7 @@ private final ContactStoreConnection.Factory connFactory; EncryptedContactStore(final URL storeUrl, final String storeAPPSEC, - final File pubKey, final SchemaFactory<ReviewDb> schema, + final Path pubKey, final SchemaFactory<ReviewDb> schema, final ContactStoreConnection.Factory connFactory) { this.storeUrl = storeUrl; this.storeAPPSEC = storeAPPSEC; @@ -104,8 +104,8 @@ return true; } - private static PGPPublicKeyRingCollection readPubRing(final File pub) { - try (InputStream fin = new FileInputStream(pub); + private static PGPPublicKeyRingCollection readPubRing(Path pub) { + try (InputStream fin = Files.newInputStream(pub); InputStream in = PGPUtil.getDecoderStream(fin)) { return new PGPPublicKeyRingCollection(in); } catch (IOException | PGPException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditModifier.java b/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditModifier.java index 87895e9..d48d0e4 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditModifier.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditModifier.java
@@ -29,6 +29,7 @@ import com.google.gerrit.extensions.restapi.ResourceConflictException; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.GerritPersonIdent; import com.google.gerrit.server.IdentifiedUser; @@ -115,26 +116,20 @@ } IdentifiedUser me = (IdentifiedUser) currentUser.get(); - Repository repo = gitManager.openRepository(change.getProject()); String refPrefix = editRefPrefix(me.getAccountId(), change.getId()); - try { + try (Repository repo = gitManager.openRepository(change.getProject())) { Map<String, Ref> refs = repo.getRefDatabase().getRefs(refPrefix); if (!refs.isEmpty()) { throw new ResourceConflictException("edit already exists"); } - RevWalk rw = new RevWalk(repo); - try { + try (RevWalk rw = new RevWalk(repo)) { ObjectId revision = ObjectId.fromString(ps.getRevision().get()); String editRefName = editRefName(me.getAccountId(), change.getId(), ps.getId()); return update(repo, me, editRefName, rw, ObjectId.zeroId(), revision); - } finally { - rw.release(); } - } finally { - repo.close(); } } @@ -159,59 +154,51 @@ IdentifiedUser me = (IdentifiedUser) currentUser.get(); String refName = editRefName(me.getAccountId(), change.getId(), current.getId()); - Repository repo = gitManager.openRepository(change.getProject()); - try { - RevWalk rw = new RevWalk(repo); + try (Repository repo = gitManager.openRepository(change.getProject()); + RevWalk rw = new RevWalk(repo); + ObjectInserter inserter = repo.newObjectInserter()) { BatchRefUpdate ru = repo.getRefDatabase().newBatchUpdate(); - ObjectInserter inserter = repo.newObjectInserter(); - try { - RevCommit editCommit = edit.getEditCommit(); - if (editCommit.getParentCount() == 0) { - throw new InvalidChangeOperationException( - "Rebase edit against root commit not supported"); - } - RevCommit tip = rw.parseCommit(ObjectId.fromString( - current.getRevision().get())); - ThreeWayMerger m = MergeStrategy.RESOLVE.newMerger(repo, true); - m.setObjectInserter(inserter); - m.setBase(ObjectId.fromString( - edit.getBasePatchSet().getRevision().get())); - - if (m.merge(tip, editCommit)) { - ObjectId tree = m.getResultTreeId(); - - CommitBuilder commit = new CommitBuilder(); - commit.setTreeId(tree); - for (int i = 0; i < tip.getParentCount(); i++) { - commit.addParentId(tip.getParent(i)); - } - commit.setAuthor(editCommit.getAuthorIdent()); - commit.setCommitter(new PersonIdent( - editCommit.getCommitterIdent(), TimeUtil.nowTs())); - commit.setMessage(editCommit.getFullMessage()); - ObjectId newEdit = inserter.insert(commit); - inserter.flush(); - - ru.addCommand(new ReceiveCommand(ObjectId.zeroId(), newEdit, - refName)); - ru.addCommand(new ReceiveCommand(edit.getRef().getObjectId(), - ObjectId.zeroId(), edit.getRefName())); - ru.execute(rw, NullProgressMonitor.INSTANCE); - for (ReceiveCommand cmd : ru.getCommands()) { - if (cmd.getResult() != ReceiveCommand.Result.OK) { - throw new IOException("failed: " + cmd); - } - } - } else { - // TODO(davido): Allow to resolve conflicts inline - throw new ResourceConflictException("merge conflict"); - } - } finally { - rw.release(); - inserter.release(); + RevCommit editCommit = edit.getEditCommit(); + if (editCommit.getParentCount() == 0) { + throw new InvalidChangeOperationException( + "Rebase edit against root commit not supported"); } - } finally { - repo.close(); + RevCommit tip = rw.parseCommit(ObjectId.fromString( + current.getRevision().get())); + ThreeWayMerger m = MergeStrategy.RESOLVE.newMerger(repo, true); + m.setObjectInserter(inserter); + m.setBase(ObjectId.fromString( + edit.getBasePatchSet().getRevision().get())); + + if (m.merge(tip, editCommit)) { + ObjectId tree = m.getResultTreeId(); + + CommitBuilder commit = new CommitBuilder(); + commit.setTreeId(tree); + for (int i = 0; i < tip.getParentCount(); i++) { + commit.addParentId(tip.getParent(i)); + } + commit.setAuthor(editCommit.getAuthorIdent()); + commit.setCommitter(new PersonIdent( + editCommit.getCommitterIdent(), TimeUtil.nowTs())); + commit.setMessage(editCommit.getFullMessage()); + ObjectId newEdit = inserter.insert(commit); + inserter.flush(); + + ru.addCommand(new ReceiveCommand(ObjectId.zeroId(), newEdit, + refName)); + ru.addCommand(new ReceiveCommand(edit.getRef().getObjectId(), + ObjectId.zeroId(), edit.getRefName())); + ru.execute(rw, NullProgressMonitor.INSTANCE); + for (ReceiveCommand cmd : ru.getCommands()) { + if (cmd.getResult() != ReceiveCommand.Result.OK) { + throw new IOException("failed: " + cmd); + } + } + } else { + // TODO(davido): Allow to resolve conflicts inline + throw new ResourceConflictException("merge conflict"); + } } } @@ -240,23 +227,16 @@ } IdentifiedUser me = (IdentifiedUser) currentUser.get(); - Repository repo = gitManager.openRepository(edit.getChange().getProject()); - try { - RevWalk rw = new RevWalk(repo); - ObjectInserter inserter = repo.newObjectInserter(); - try { - String refName = edit.getRefName(); - ObjectId commit = createCommit(me, inserter, prevEdit, - prevEdit.getTree(), - msg); - inserter.flush(); - return update(repo, me, refName, rw, prevEdit, commit); - } finally { - rw.release(); - inserter.release(); - } - } finally { - repo.close(); + Project.NameKey project = edit.getChange().getProject(); + try (Repository repo = gitManager.openRepository(project); + RevWalk rw = new RevWalk(repo); + ObjectInserter inserter = repo.newObjectInserter()) { + String refName = edit.getRefName(); + ObjectId commit = createCommit(me, inserter, prevEdit, + prevEdit.getTree(), + msg); + inserter.flush(); + return update(repo, me, refName, rw, prevEdit, commit); } } @@ -333,36 +313,28 @@ throw new AuthException("Authentication required"); } IdentifiedUser me = (IdentifiedUser) currentUser.get(); - Repository repo = gitManager.openRepository(edit.getChange().getProject()); - try { - RevWalk rw = new RevWalk(repo); - ObjectInserter inserter = repo.newObjectInserter(); - ObjectReader reader = repo.newObjectReader(); - try { - String refName = edit.getRefName(); - RevCommit prevEdit = edit.getEditCommit(); - ObjectId newTree = writeNewTree(op, - rw, - inserter, - prevEdit, - reader, - file, - newFile, - toBlob(inserter, content)); - if (ObjectId.equals(newTree, prevEdit.getTree())) { - throw new InvalidChangeOperationException("no changes were made"); - } - - ObjectId commit = createCommit(me, inserter, prevEdit, newTree); - inserter.flush(); - return update(repo, me, refName, rw, prevEdit, commit); - } finally { - rw.release(); - inserter.release(); - reader.release(); + Project.NameKey project = edit.getChange().getProject(); + try (Repository repo = gitManager.openRepository(project); + RevWalk rw = new RevWalk(repo); + ObjectInserter inserter = repo.newObjectInserter(); + ObjectReader reader = repo.newObjectReader()) { + String refName = edit.getRefName(); + RevCommit prevEdit = edit.getEditCommit(); + ObjectId newTree = writeNewTree(op, + rw, + inserter, + prevEdit, + reader, + file, + newFile, + toBlob(inserter, content)); + if (ObjectId.equals(newTree, prevEdit.getTree())) { + throw new InvalidChangeOperationException("no changes were made"); } - } finally { - repo.close(); + + ObjectId commit = createCommit(me, inserter, prevEdit, newTree); + inserter.flush(); + return update(repo, me, refName, rw, prevEdit, commit); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditUtil.java index 3635b56..3d2aa6f 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditUtil.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditUtil.java
@@ -109,8 +109,7 @@ */ public Optional<ChangeEdit> byChange(Change change, IdentifiedUser user) throws IOException { - Repository repo = gitManager.openRepository(change.getProject()); - try { + try (Repository repo = gitManager.openRepository(change.getProject())) { String editRefPrefix = editRefPrefix(user.getAccountId(), change.getId()); Map<String, Ref> refs = repo.getRefDatabase().getRefs(editRefPrefix); if (refs.isEmpty()) { @@ -121,16 +120,11 @@ // where there is more than one ref, we could silently delete all but the // current one. Ref ref = Iterables.getOnlyElement(refs.values()); - RevWalk rw = new RevWalk(repo); - try { + try (RevWalk rw = new RevWalk(repo)) { RevCommit commit = rw.parseCommit(ref.getObjectId()); PatchSet basePs = getBasePatchSet(change, ref); return Optional.of(new ChangeEdit(user, change, ref, commit, basePs)); - } finally { - rw.release(); } - } finally { - repo.close(); } } @@ -150,29 +144,19 @@ NoSuchChangeException, IOException, InvalidChangeOperationException, OrmException, ResourceConflictException { Change change = edit.getChange(); - Repository repo = gitManager.openRepository(change.getProject()); - try { - RevWalk rw = new RevWalk(repo); - ObjectInserter inserter = repo.newObjectInserter(); - try { - - PatchSet basePatchSet = edit.getBasePatchSet(); - if (!basePatchSet.getId().equals(change.currentPatchSetId())) { - throw new ResourceConflictException( - "only edit for current patch set can be published"); - } - - insertPatchSet(edit, change, repo, rw, basePatchSet, - squashEdit(rw, inserter, edit.getEditCommit(), basePatchSet)); - } finally { - inserter.release(); - rw.release(); + try (Repository repo = gitManager.openRepository(change.getProject()); + RevWalk rw = new RevWalk(repo); + ObjectInserter inserter = repo.newObjectInserter()) { + PatchSet basePatchSet = edit.getBasePatchSet(); + if (!basePatchSet.getId().equals(change.currentPatchSetId())) { + throw new ResourceConflictException( + "only edit for current patch set can be published"); } + insertPatchSet(edit, change, repo, rw, basePatchSet, + squashEdit(rw, inserter, edit.getEditCommit(), basePatchSet)); // TODO(davido): This should happen in the same BatchRefUpdate. deleteRef(repo, edit); - } finally { - repo.close(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java index 21465ef..d8e56b3 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/BanCommit.java
@@ -101,46 +101,38 @@ NoteMap banCommitNotes = NoteMap.newEmptyMap(); // Add a note for each banned commit to notes. final Project.NameKey project = projectControl.getProject().getNameKey(); - final Repository repo = repoManager.openRepository(project); - try { - final RevWalk revWalk = new RevWalk(repo); - final ObjectInserter inserter = repo.newObjectInserter(); - try { - ObjectId noteId = null; - for (final ObjectId commitToBan : commitsToBan) { - try { - revWalk.parseCommit(commitToBan); - } catch (MissingObjectException e) { - // Ignore exception, non-existing commits can be banned. - } catch (IncorrectObjectTypeException e) { - result.notACommit(commitToBan); - continue; - } - if (noteId == null) { - noteId = createNoteContent(reason, inserter); - } - banCommitNotes.set(commitToBan, noteId); + try (Repository repo = repoManager.openRepository(project); + RevWalk revWalk = new RevWalk(repo); + ObjectInserter inserter = repo.newObjectInserter()) { + ObjectId noteId = null; + for (final ObjectId commitToBan : commitsToBan) { + try { + revWalk.parseCommit(commitToBan); + } catch (MissingObjectException e) { + // Ignore exception, non-existing commits can be banned. + } catch (IncorrectObjectTypeException e) { + result.notACommit(commitToBan); + continue; } - NotesBranchUtil notesBranchUtil = - notesBranchUtilFactory.create(project, repo, inserter); - NoteMap newlyCreated = - notesBranchUtil.commitNewNotes(banCommitNotes, REFS_REJECT_COMMITS, - createPersonIdent(), buildCommitMessage(commitsToBan, reason)); - - for (Note n : banCommitNotes) { - if (newlyCreated.contains(n)) { - result.commitBanned(n); - } else { - result.commitAlreadyBanned(n); - } + if (noteId == null) { + noteId = createNoteContent(reason, inserter); } - return result; - } finally { - revWalk.release(); - inserter.release(); + banCommitNotes.set(commitToBan, noteId); } - } finally { - repo.close(); + NotesBranchUtil notesBranchUtil = + notesBranchUtilFactory.create(project, repo, inserter); + NoteMap newlyCreated = + notesBranchUtil.commitNewNotes(banCommitNotes, REFS_REJECT_COMMITS, + createPersonIdent(), buildCommitMessage(commitsToBan, reason)); + + for (Note n : banCommitNotes) { + if (newlyCreated.contains(n)) { + result.commitBanned(n); + } else { + result.commitAlreadyBanned(n); + } + } + return result; } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java index 633c3bb..4f7c1db 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java
@@ -51,7 +51,14 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.FileVisitOption; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.Collections; +import java.util.EnumSet; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.locks.Lock; @@ -128,8 +135,8 @@ } } - private final File basePath; - private final File noteDbPath; + private final Path basePath; + private final Path noteDbPath; private final Lock namesUpdateLock; private volatile SortedSet<Project.NameKey> names; @@ -153,7 +160,7 @@ } /** @return base directory under which all projects are stored. */ - public File getBasePath() { + public Path getBasePath() { return basePath; } @@ -163,12 +170,12 @@ return openRepository(basePath, name); } - private Repository openRepository(File path, Project.NameKey name) + private Repository openRepository(Path path, Project.NameKey name) throws RepositoryNotFoundException { if (isUnreasonableName(name)) { throw new RepositoryNotFoundException("Invalid name: " + name); } - File gitDir = new File(path, name.get()); + File gitDir = path.resolve(name.get()).toFile(); if (!names.contains(name)) { // The this.names list does not hold the project-name but it can still exist // on disk; for instance when the project has been created directly on the @@ -214,13 +221,13 @@ return repo; } - private Repository createRepository(File path, Project.NameKey name) + private Repository createRepository(Path path, Project.NameKey name) throws RepositoryNotFoundException, RepositoryCaseMismatchException { if (isUnreasonableName(name)) { throw new RepositoryNotFoundException("Invalid name: " + name); } - File dir = FileKey.resolve(new File(path, name.get()), FS.DETECTED); + File dir = FileKey.resolve(path.resolve(name.get()).toFile(), FS.DETECTED); FileKey loc; if (dir != null) { // Already exists on disk, use the repository we found. @@ -235,7 +242,7 @@ // of the repository name, so prefer the standard bare name. // String n = name.get() + Constants.DOT_GIT_EXT; - loc = FileKey.exact(new File(path, n), FS.DETECTED); + loc = FileKey.exact(path.resolve(n).toFile(), FS.DETECTED); } try { @@ -397,51 +404,58 @@ // scanning the filesystem. Don't rely on the cached names collection. namesUpdateLock.lock(); try { - SortedSet<Project.NameKey> n = new TreeSet<>(); - scanProjects(basePath, "", n); - names = Collections.unmodifiableSortedSet(n); - return n; + ProjectVisitor visitor = new ProjectVisitor(); + try { + Files.walkFileTree(basePath, EnumSet.of(FileVisitOption.FOLLOW_LINKS), + Integer.MAX_VALUE, visitor); + } catch (IOException e) { + log.error("Error walking repository tree " + basePath.toAbsolutePath(), + e); + } + return Collections.unmodifiableSortedSet(visitor.found); } finally { namesUpdateLock.unlock(); } } - private void scanProjects(final File dir, final String prefix, - final SortedSet<Project.NameKey> names) { - final File[] ls = dir.listFiles(); - if (ls == null) { - return; + private class ProjectVisitor extends SimpleFileVisitor<Path> { + private final SortedSet<Project.NameKey> found = new TreeSet<>(); + + @Override + public FileVisitResult preVisitDirectory(Path dir, + BasicFileAttributes attrs) throws IOException { + if (!dir.equals(basePath) && isRepo(dir)) { + addProject(dir); + return FileVisitResult.SKIP_SUBTREE; + } + return FileVisitResult.CONTINUE; } - for (File f : ls) { - String fileName = f.getName(); - if (fileName.equals(Constants.DOT_GIT)) { - // Skip repositories named only `.git` - } else if (FileKey.isGitRepository(f, FS.DETECTED)) { - Project.NameKey nameKey = getProjectName(prefix, fileName); - if (isUnreasonableName(nameKey)) { - log.warn("Ignoring unreasonably named repository " + f.getAbsolutePath()); - } else { - names.add(nameKey); - } + private boolean isRepo(Path p) { + return !p.getFileName().toString().equals(Constants.DOT_GIT) + && FileKey.isGitRepository(p.toFile(), FS.DETECTED); + } - } else if (f.isDirectory()) { - scanProjects(f, prefix + f.getName() + "/", names); + private void addProject(Path p) { + Project.NameKey nameKey = getProjectName(p); + if (isUnreasonableName(nameKey)) { + log.warn( + "Ignoring unreasonably named repository " + p.toAbsolutePath()); + } else { + found.add(nameKey); } } - } - private Project.NameKey getProjectName(final String prefix, - final String fileName) { - final String projectName; - if (fileName.endsWith(Constants.DOT_GIT_EXT)) { - int newLen = fileName.length() - Constants.DOT_GIT_EXT.length(); - projectName = prefix + fileName.substring(0, newLen); - - } else { - projectName = prefix + fileName; + private Project.NameKey getProjectName(Path p) { + String projectName = basePath.relativize(p).toString(); + if (File.separatorChar != '/') { + projectName = projectName.replace(File.separatorChar, '/'); + } + if (projectName.endsWith(Constants.DOT_GIT_EXT)) { + int newLen = projectName.length() - Constants.DOT_GIT_EXT.length(); + projectName = projectName.substring(0, newLen); + } + return new Project.NameKey(projectName); } - - return new Project.NameKey(projectName); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java index 7d3e1b3..05e864b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
@@ -332,10 +332,10 @@ throw new MergeException("Cannot query the database", e); } finally { if (inserter != null) { - inserter.release(); + inserter.close(); } if (rw != null) { - rw.release(); + rw.close(); } if (repo != null) { repo.close();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java index f1b0a78..fb96a6b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/NotesBranchUtil.java
@@ -153,8 +153,8 @@ } updateRef(notesBranch); } finally { - revWalk.release(); - reader.release(); + revWalk.close(); + reader.close(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java index cbf5701..96dcc9a 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -1729,18 +1729,15 @@ throws OrmException, IOException { Submit submit = submitProvider.get(); RevisionResource rsrc = new RevisionResource(changes.parse(changeCtl), ps); - Change c; + List<Change> changes; try { // Force submit even if submit rule evaluation fails. - c = submit.submit(rsrc, currentUser, true); + changes = submit.submit(rsrc, currentUser, true); } catch (ResourceConflictException e) { throw new IOException(e); } - if (c == null) { - addError("Submitting change " + changeCtl.getChange().getChangeId() - + " failed."); - } else { - addMessage(""); + addMessage(""); + for (Change c : changes) { mergeQueue.merge(c.getDest()); c = db.changes().get(c.getId()); switch (c.getStatus()) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmoduleOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmoduleOp.java index 0e5d9fb..3cf9fed 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmoduleOp.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmoduleOp.java
@@ -382,7 +382,7 @@ + subscriber.get(), e); } finally { if (recRw != null) { - recRw.release(); + recRw.close(); } if (pdb != null) { pdb.close(); @@ -392,8 +392,7 @@ private static DirCache readTree(final Repository pdb, final Ref branch) throws MissingObjectException, IncorrectObjectTypeException, IOException { - final RevWalk rw = new RevWalk(pdb); - try { + try (RevWalk rw = new RevWalk(pdb)) { final DirCache dc = DirCache.newInCore(); final DirCacheBuilder b = dc.builder(); b.addTree(new byte[0], // no prefix path @@ -401,8 +400,6 @@ pdb.newObjectReader(), rw.parseTree(branch.getObjectId())); b.finish(); return dc; - } finally { - rw.release(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSet.java index 799e220..a003235 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSet.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSet.java
@@ -147,7 +147,7 @@ } } finally { if (rw != null) { - rw.release(); + rw.close(); } } } @@ -157,9 +157,8 @@ return; } - TagWalk rw = new TagWalk(git); - rw.setRetainBody(false); - try { + try (TagWalk rw = new TagWalk(git)) { + rw.setRetainBody(false); for (Ref ref : git.getRefDatabase().getRefs(RefDatabase.ALL).values()) { if (skip(ref)) { continue; @@ -188,8 +187,6 @@ } } catch (IOException e) { log.warn("Error building tags for repository " + projectName, e); - } finally { - rw.release(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java index 8dab448..b905f67 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
@@ -122,7 +122,7 @@ revision = id != null ? new RevWalk(reader).parseCommit(id) : null; onLoad(); } finally { - reader.release(); + reader.close(); reader = null; } } @@ -319,13 +319,14 @@ public void close() { newTree = null; + rw.close(); if (inserter != null) { - inserter.release(); + inserter.close(); inserter = null; } if (reader != null) { - reader.release(); + reader.close(); reader = null; } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java index a0c27c4..c0522d5 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java
@@ -323,41 +323,36 @@ getPathsAndIndex(id); } } finally { - walk.release(); + walk.close(); } return null; } private void getPathsAndIndex(ObjectId b) throws Exception { List<ChangeData> cds = Lists.newArrayList(byId.get(b)); - try { + try (DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE)) { RevCommit bCommit = walk.parseCommit(b); RevTree bTree = bCommit.getTree(); RevTree aTree = aFor(bCommit, walk); - DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE); - try { - df.setRepository(repo); - if (!cds.isEmpty()) { - List<String> paths = (aTree != null) - ? getPaths(df.scan(aTree, bTree)) - : Collections.<String>emptyList(); - Iterator<ChangeData> cdit = cds.iterator(); - for (ChangeData cd ; cdit.hasNext(); cdit.remove()) { - cd = cdit.next(); - try { - cd.setCurrentFilePaths(paths); - indexer.index(cd); - done.update(1); - if (verboseWriter != null) { - verboseWriter.println("Reindexed change " + cd.getId()); - } - } catch (Exception e) { - fail("Failed to index change " + cd.getId(), true, e); + df.setRepository(repo); + if (!cds.isEmpty()) { + List<String> paths = (aTree != null) + ? getPaths(df.scan(aTree, bTree)) + : Collections.<String>emptyList(); + Iterator<ChangeData> cdit = cds.iterator(); + for (ChangeData cd ; cdit.hasNext(); cdit.remove()) { + cd = cdit.next(); + try { + cd.setCurrentFilePaths(paths); + indexer.index(cd); + done.update(1); + if (verboseWriter != null) { + verboseWriter.println("Reindexed change " + cd.getId()); } + } catch (Exception e) { + fail("Failed to index change " + cd.getId(), true, e); } } - } finally { - df.release(); } } catch (Exception e) { fail("Failed to index commit " + b.name(), false, e); @@ -396,13 +391,10 @@ } private ObjectId emptyTree() throws IOException { - ObjectInserter oi = repo.newObjectInserter(); - try { + try (ObjectInserter oi = repo.newObjectInserter()) { ObjectId id = oi.insert(Constants.OBJ_TREE, new byte[] {}); oi.flush(); return id; - } finally { - oi.release(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java index 405b3a8..ac23455 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java
@@ -396,28 +396,28 @@ TemporaryBuffer.Heap buf = new TemporaryBuffer.Heap(args.settings.maximumDiffSize); - DiffFormatter fmt = new DiffFormatter(buf); - Repository git; - try { - git = args.server.openRepository(change.getProject()); - } catch (IOException e) { - log.error("Cannot open repository to format patch", e); - return ""; - } - try { - fmt.setRepository(git); - fmt.setDetectRenames(true); - fmt.format(patchList.getOldId(), patchList.getNewId()); - return RawParseUtils.decode(buf.toByteArray()); - } catch (IOException e) { - if (JGitText.get().inMemoryBufferLimitExceeded.equals(e.getMessage())) { + try (DiffFormatter fmt = new DiffFormatter(buf)) { + Repository git; + try { + git = args.server.openRepository(change.getProject()); + } catch (IOException e) { + log.error("Cannot open repository to format patch", e); return ""; } - log.error("Cannot format patch", e); - return ""; - } finally { - fmt.release(); - git.close(); + try { + fmt.setRepository(git); + fmt.setDetectRenames(true); + fmt.format(patchList.getOldId(), patchList.getNewId()); + return RawParseUtils.decode(buf.toByteArray()); + } catch (IOException e) { + if (JGitText.get().inMemoryBufferLimitExceeded.equals(e.getMessage())) { + return ""; + } + log.error("Cannot format patch", e); + return ""; + } finally { + git.close(); + } } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/PatchSetNotificationSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/PatchSetNotificationSender.java index 667d834..53efa1e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/PatchSetNotificationSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/PatchSetNotificationSender.java
@@ -82,15 +82,11 @@ final Change updatedChange, final PatchSet updatedPatchSet, final LabelTypes labelTypes) throws OrmException, IOException { - final Repository git = repoManager.openRepository(updatedChange.getProject()); - try { - final RevWalk revWalk = new RevWalk(git); + try (Repository git = repoManager.openRepository(updatedChange.getProject())) { final RevCommit commit; - try { + try (RevWalk revWalk = new RevWalk(git)) { commit = revWalk.parseCommit(ObjectId.fromString( updatedPatchSet.getRevision().get())); - } finally { - revWalk.release(); } final PatchSetInfo info = patchSetInfoFactory.get(commit, updatedPatchSet.getId()); final List<FooterLine> footerLines = commit.getFooterLines(); @@ -134,8 +130,6 @@ log.error("Cannot send email for new patch set " + updatedPatchSet.getId(), e); } } - } finally { - git.close(); } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/VelocityRuntimeProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/VelocityRuntimeProvider.java index ace1f5b..101aaac 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/VelocityRuntimeProvider.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/VelocityRuntimeProvider.java
@@ -26,6 +26,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.nio.file.Files; import java.util.Properties; /** Configures Velocity template engine for sending email. */ @@ -49,10 +50,11 @@ p.setProperty(RuntimeConstants.RUNTIME_REFERENCES_STRICT, "true"); p.setProperty("runtime.log.logsystem.log4j.category", "velocity"); - if (site.mail_dir.isDirectory()) { + if (Files.isDirectory(site.mail_dir)) { p.setProperty(rl, "file, class"); p.setProperty("file." + rl + ".class", pkg + ".FileResourceLoader"); - p.setProperty("file." + rl + ".path", site.mail_dir.getAbsolutePath()); + p.setProperty("file." + rl + ".path", + site.mail_dir.toAbsolutePath().toString()); p.setProperty("class." + rl + ".class", pkg + ".ClasspathResourceLoader"); } else { p.setProperty(rl, "class");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java index e97111d..6d4f3a4 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java
@@ -272,9 +272,9 @@ loadDefaults(); return; } - RevWalk walk = new RevWalk(reader); - try (ChangeNotesParser parser = - new ChangeNotesParser(change, rev, walk, repoManager)) { + try (RevWalk walk = new RevWalk(reader); + ChangeNotesParser parser = + new ChangeNotesParser(change, rev, walk, repoManager)) { parser.parseAll(); if (parser.status != null) { @@ -301,8 +301,6 @@ this.allPastReviewers = ImmutableList.copyOf(parser.allPastReviewers); submitRecords = ImmutableList.copyOf(parser.submitRecords); - } finally { - walk.release(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeRebuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeRebuilder.java index 1053f09..76dfdc8 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeRebuilder.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeRebuilder.java
@@ -200,12 +200,9 @@ private void writeToBatch(BatchMetaDataUpdate batch, AbstractChangeUpdate update, Repository repo) throws IOException, OrmException { - ObjectInserter inserter = repo.newObjectInserter(); - try { + try (ObjectInserter inserter = repo.newObjectInserter()) { update.setInserter(inserter); update.writeCommit(batch); - } finally { - inserter.release(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/DraftCommentNotes.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/DraftCommentNotes.java index d40358b..20d6c4a 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/DraftCommentNotes.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/DraftCommentNotes.java
@@ -132,16 +132,14 @@ return; } - RevWalk walk = new RevWalk(reader); - try (DraftCommentNotesParser parser = new DraftCommentNotesParser( - getChangeId(), walk, rev, repoManager, draftsProject, author)) { + try (RevWalk walk = new RevWalk(reader); + DraftCommentNotesParser parser = new DraftCommentNotesParser( + getChangeId(), walk, rev, repoManager, draftsProject, author)) { parser.parseDraftComments(); buildCommentTable(draftBaseComments, parser.draftBaseComments); buildCommentTable(draftPsComments, parser.draftPsComments); noteMap = parser.noteMap; - } finally { - walk.release(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchFile.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchFile.java index 2e63a76..8740a6b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchFile.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchFile.java
@@ -48,9 +48,8 @@ this.repo = repo; this.entry = patchList.get(fileName); - final ObjectReader reader = repo.newObjectReader(); - try { - final RevWalk rw = new RevWalk(reader); + try (ObjectReader reader = repo.newObjectReader(); + RevWalk rw = new RevWalk(reader)) { final RevCommit bCommit = rw.parseCommit(patchList.getNewId()); if (Patch.COMMIT_MSG.equals(fileName)) { @@ -74,8 +73,6 @@ } bTree = bCommit.getTree(); } - } finally { - reader.release(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java index 0c8c5ec..bfb8c00 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
@@ -116,9 +116,9 @@ private PatchList readPatchList(final PatchListKey key, final Repository repo) throws IOException, PatchListNotAvailableException { final RawTextComparator cmp = comparatorFor(key.getWhitespace()); - final ObjectReader reader = repo.newObjectReader(); - try { - final RevWalk rw = new RevWalk(reader); + try (ObjectReader reader = repo.newObjectReader(); + RevWalk rw = new RevWalk(reader); + DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE)) { final RevCommit b = rw.parseCommit(key.getNewId()); final RevObject a = aFor(key, repo, rw, b); @@ -138,7 +138,6 @@ RevTree aTree = rw.parseTree(a); RevTree bTree = b.getTree(); - DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE); df.setRepository(repo); df.setDiffComparator(cmp); df.setDetectRenames(true); @@ -170,8 +169,6 @@ } return new PatchList(a, b, againstParent, entries.toArray(new PatchListEntry[entries.size()])); - } finally { - reader.release(); } } @@ -271,8 +268,7 @@ } ResolveMerger m = (ResolveMerger) mergeStrategy.newMerger(repo, true); - final ObjectInserter ins = repo.newObjectInserter(); - try { + try (ObjectInserter ins = repo.newObjectInserter()) { DirCache dc = DirCache.newInCore(); m.setDirCache(dc); m.setObjectInserter(new ObjectInserter.Filter() { @@ -397,19 +393,14 @@ } return rw.lookupTree(treeId); - } finally { - ins.release(); } } private static ObjectId emptyTree(final Repository repo) throws IOException { - ObjectInserter oi = repo.newObjectInserter(); - try { + try (ObjectInserter oi = repo.newObjectInserter()) { ObjectId id = oi.insert(Constants.OBJ_TREE, new byte[] {}); oi.flush(); return id; - } finally { - oi.release(); } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchScriptBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchScriptBuilder.java index d231664..ea427eb 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchScriptBuilder.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchScriptBuilder.java
@@ -119,7 +119,7 @@ try { return build(content, comments, history); } finally { - reader.release(); + reader.close(); } } @@ -514,9 +514,10 @@ if (path == null || within == null) { return null; } - final RevWalk rw = new RevWalk(reader); - final RevTree tree = rw.parseTree(within); - return TreeWalk.forPath(reader, path, tree); + try (RevWalk rw = new RevWalk(reader)) { + final RevTree tree = rw.parseTree(within); + return TreeWalk.forPath(reader, path, tree); + } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java index 340300a..1e4ffce 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java
@@ -85,17 +85,12 @@ } catch (IOException e) { throw new PatchSetInfoNotAvailableException(e); } - try { - final RevWalk rw = new RevWalk(repo); - try { - final RevCommit src = - rw.parseCommit(ObjectId.fromString(patchSet.getRevision().get())); - PatchSetInfo info = get(src, patchSet.getId()); - info.setParents(toParentInfos(src.getParents(), rw)); - return info; - } finally { - rw.release(); - } + try (RevWalk rw = new RevWalk(repo)) { + final RevCommit src = + rw.parseCommit(ObjectId.fromString(patchSet.getRevision().get())); + PatchSetInfo info = get(src, patchSet.getId()); + info.setParents(toParentInfos(src.getParents(), rw)); + return info; } catch (IOException e) { throw new PatchSetInfoNotAvailableException(e); } finally {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/Text.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/Text.java index 1939c84..882e25f 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/Text.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/Text.java
@@ -44,44 +44,45 @@ public static final Text EMPTY = new Text(NO_BYTES); public static Text forCommit(ObjectReader reader, AnyObjectId commitId) throws IOException { - RevWalk rw = new RevWalk(reader); - RevCommit c; - if (commitId instanceof RevCommit) { - c = (RevCommit) commitId; - } else { - c = rw.parseCommit(commitId); - } - - StringBuilder b = new StringBuilder(); - switch (c.getParentCount()) { - case 0: - break; - case 1: { - RevCommit p = c.getParent(0); - rw.parseBody(p); - b.append("Parent: "); - b.append(reader.abbreviate(p, 8).name()); - b.append(" ("); - b.append(p.getShortMessage()); - b.append(")\n"); - break; + try (RevWalk rw = new RevWalk(reader)) { + RevCommit c; + if (commitId instanceof RevCommit) { + c = (RevCommit) commitId; + } else { + c = rw.parseCommit(commitId); } - default: - for (int i = 0; i < c.getParentCount(); i++) { - RevCommit p = c.getParent(i); + + StringBuilder b = new StringBuilder(); + switch (c.getParentCount()) { + case 0: + break; + case 1: { + RevCommit p = c.getParent(0); rw.parseBody(p); - b.append(i == 0 ? "Merge Of: " : " "); + b.append("Parent: "); b.append(reader.abbreviate(p, 8).name()); b.append(" ("); b.append(p.getShortMessage()); b.append(")\n"); + break; } + default: + for (int i = 0; i < c.getParentCount(); i++) { + RevCommit p = c.getParent(i); + rw.parseBody(p); + b.append(i == 0 ? "Merge Of: " : " "); + b.append(reader.abbreviate(p, 8).name()); + b.append(" ("); + b.append(p.getShortMessage()); + b.append(")\n"); + } + } + appendPersonIdent(b, "Author", c.getAuthorIdent()); + appendPersonIdent(b, "Commit", c.getCommitterIdent()); + b.append("\n"); + b.append(c.getFullMessage()); + return new Text(b.toString().getBytes("UTF-8")); } - appendPersonIdent(b, "Author", c.getAuthorIdent()); - appendPersonIdent(b, "Commit", c.getCommitterIdent()); - b.append("\n"); - b.append(c.getFullMessage()); - return new Text(b.toString().getBytes("UTF-8")); } private static void appendPersonIdent(StringBuilder b, String field,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CleanupHandle.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CleanupHandle.java index 593f2c9..9827812 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CleanupHandle.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CleanupHandle.java
@@ -14,17 +14,17 @@ package com.google.gerrit.server.plugins; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.jar.JarFile; class CleanupHandle { - private final File tmpFile; + private final Path tmp; private final JarFile jarFile; - CleanupHandle(File tmpFile, - JarFile jarFile) { - this.tmpFile = tmpFile; + CleanupHandle(Path tmp, JarFile jarFile) { + this.tmp = tmp; this.jarFile = jarFile; } @@ -34,12 +34,13 @@ } catch (IOException err) { PluginLoader.log.error("Cannot close " + jarFile.getName(), err); } - if (!tmpFile.delete() && tmpFile.exists()) { - PluginLoader.log.warn("Cannot delete " + tmpFile.getAbsolutePath() - + ", retrying to delete it on termination of the virtual machine"); - tmpFile.deleteOnExit(); - } else { - PluginLoader.log.info("Cleaned plugin " + tmpFile.getName()); + try { + Files.deleteIfExists(tmp); + PluginLoader.log.info("Cleaned plugin " + tmp.getFileName()); + } catch (IOException e) { + PluginLoader.log.warn("Cannot delete " + tmp.toAbsolutePath() + + ", retrying to delete it on termination of the virtual machine", e); + tmp.toFile().deleteOnExit(); } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CopyConfigModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CopyConfigModule.java index 7252617..1d4233a 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CopyConfigModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/CopyConfigModule.java
@@ -33,7 +33,7 @@ import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.PersonIdent; -import java.io.File; +import java.nio.file.Path; /** * Copies critical objects from the {@code dbInjector} into a plugin. @@ -47,11 +47,11 @@ class CopyConfigModule extends AbstractModule { @Inject @SitePath - private File sitePath; + private Path sitePath; @Provides @SitePath - File getSitePath() { + Path getSitePath() { return sitePath; }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPluginProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPluginProvider.java index 53f39f1..dcfb52c 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPluginProvider.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPluginProvider.java
@@ -24,13 +24,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -43,7 +44,7 @@ static final String JAR_EXTENSION = ".jar"; static final Logger log = LoggerFactory.getLogger(JarPluginProvider.class); - private final File tmpDir; + private final Path tmpDir; @Inject JarPluginProvider(SitePaths sitePaths) { @@ -51,42 +52,42 @@ } @Override - public boolean handles(File srcFile) { - String fileName = srcFile.getName(); + public boolean handles(Path srcPath) { + String fileName = srcPath.getFileName().toString(); return fileName.endsWith(JAR_EXTENSION) || fileName.endsWith(JAR_EXTENSION + ".disabled"); } @Override - public String getPluginName(File srcFile) { + public String getPluginName(Path srcPath) { try { - return MoreObjects.firstNonNull(getJarPluginName(srcFile), - PluginLoader.nameOf(srcFile)); + return MoreObjects.firstNonNull(getJarPluginName(srcPath), + PluginLoader.nameOf(srcPath)); } catch (IOException e) { - throw new IllegalArgumentException("Invalid plugin file " + srcFile + throw new IllegalArgumentException("Invalid plugin file " + srcPath + ": cannot get plugin name", e); } } - public static String getJarPluginName(File srcFile) throws IOException { - try (JarFile jarFile = new JarFile(srcFile)) { + public static String getJarPluginName(Path srcPath) throws IOException { + try (JarFile jarFile = new JarFile(srcPath.toFile())) { return jarFile.getManifest().getMainAttributes() .getValue("Gerrit-PluginName"); } } @Override - public ServerPlugin get(File srcFile, FileSnapshot snapshot, + public ServerPlugin get(Path srcPath, FileSnapshot snapshot, PluginDescription description) throws InvalidPluginException { try { - String name = getPluginName(srcFile); - String extension = getExtension(srcFile); - try (FileInputStream in = new FileInputStream(srcFile)) { - File tmp = asTemp(in, tempNameFor(name), extension, tmpDir); - return loadJarPlugin(name, srcFile, snapshot, tmp, description); + String name = getPluginName(srcPath); + String extension = getExtension(srcPath); + try (InputStream in = Files.newInputStream(srcPath)) { + Path tmp = asTemp(in, tempNameFor(name), extension, tmpDir); + return loadJarPlugin(name, srcPath, snapshot, tmp, description); } } catch (IOException e) { - throw new InvalidPluginException("Cannot load Jar plugin " + srcFile, e); + throw new InvalidPluginException("Cannot load Jar plugin " + srcPath, e); } } @@ -95,8 +96,8 @@ return "gerrit"; } - private static String getExtension(File file) { - return getExtension(file.getName()); + private static String getExtension(Path path) { + return getExtension(path.getFileName().toString()); } private static String getExtension(String name) { @@ -109,18 +110,18 @@ return PLUGIN_TMP_PREFIX + name + "_" + fmt.format(new Date()) + "_"; } - public static File storeInTemp(String pluginName, InputStream in, + public static Path storeInTemp(String pluginName, InputStream in, SitePaths sitePaths) throws IOException { - if (!sitePaths.tmp_dir.exists()) { - sitePaths.tmp_dir.mkdirs(); + if (!Files.exists(sitePaths.tmp_dir)) { + Files.createDirectories(sitePaths.tmp_dir); } return asTemp(in, tempNameFor(pluginName), ".jar", sitePaths.tmp_dir); } - private ServerPlugin loadJarPlugin(String name, File srcJar, - FileSnapshot snapshot, File tmp, PluginDescription description) + private ServerPlugin loadJarPlugin(String name, Path srcJar, + FileSnapshot snapshot, Path tmp, PluginDescription description) throws IOException, InvalidPluginException, MalformedURLException { - JarFile jarFile = new JarFile(tmp); + JarFile jarFile = new JarFile(tmp.toFile()); boolean keep = false; try { Manifest manifest = jarFile.getManifest(); @@ -129,24 +130,22 @@ List<URL> urls = new ArrayList<>(2); String overlay = System.getProperty("gerrit.plugin-classes"); if (overlay != null) { - File classes = new File(new File(new File(overlay), name), "main"); - if (classes.isDirectory()) { - log.info(String.format("plugin %s: including %s", name, - classes.getPath())); - urls.add(classes.toURI().toURL()); + Path classes = Paths.get(overlay).resolve(name).resolve("main"); + if (Files.isDirectory(classes)) { + log.info(String.format("plugin %s: including %s", name, classes)); + urls.add(classes.toUri().toURL()); } } - urls.add(tmp.toURI().toURL()); + urls.add(tmp.toUri().toURL()); ClassLoader pluginLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), PluginLoader.parentFor(type)); JarScanner jarScanner = createJarScanner(srcJar); - ServerPlugin plugin = - new ServerPlugin(name, description.canonicalUrl, description.user, - srcJar, snapshot, jarScanner, description.dataDir, - pluginLoader); + ServerPlugin plugin = new ServerPlugin(name, description.canonicalUrl, + description.user, srcJar, snapshot, jarScanner, + description.dataDir, pluginLoader); plugin.setCleanupHandle(new CleanupHandle(tmp, jarFile)); keep = true; return plugin; @@ -157,7 +156,7 @@ } } - private JarScanner createJarScanner(File srcJar) + private JarScanner createJarScanner(Path srcJar) throws InvalidPluginException { try { return new JarScanner(srcJar);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java index a8600fe..0f4aa6c 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java
@@ -39,10 +39,10 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -69,8 +69,8 @@ private final JarFile jarFile; - public JarScanner(File srcFile) throws IOException { - this.jarFile = new JarFile(srcFile); + public JarScanner(Path src) throws IOException { + this.jarFile = new JarFile(src.toFile()); } @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JsPlugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JsPlugin.java index 63f69b5..8da8cc1 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JsPlugin.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JsPlugin.java
@@ -27,12 +27,12 @@ import org.eclipse.jgit.internal.storage.file.FileSnapshot; -import java.io.File; +import java.nio.file.Path; class JsPlugin extends Plugin { private Injector httpInjector; - JsPlugin(String name, File srcFile, PluginUser pluginUser, + JsPlugin(String name, Path srcFile, PluginUser pluginUser, FileSnapshot snapshot) { super(name, srcFile, pluginUser, snapshot, ApiType.JS); } @@ -40,7 +40,7 @@ @Override @Nullable public String getVersion() { - String fileName = getSrcFile().getName(); + String fileName = getSrcFile().getFileName().toString(); int firstDash = fileName.indexOf("-"); if (firstDash > 0) { return fileName.substring(firstDash + 1, fileName.lastIndexOf(".js")); @@ -51,7 +51,7 @@ @Override public void start(PluginGuiceEnvironment env) throws Exception { manager = new LifecycleManager(); - String fileName = getSrcFile().getName(); + String fileName = getSrcFile().getFileName().toString(); httpInjector = Guice.createInjector(new StandaloneJsPluginModule(getName(), fileName)); manager.start();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java index 54f05f0..1d717ef 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java
@@ -90,7 +90,7 @@ stdout.format("%-30s %-10s %-8s %s\n", p.getName(), Strings.nullToEmpty(info.version), p.isDisabled() ? "DISABLED" : "ENABLED", - p.getSrcFile().getName()); + p.getSrcFile().getFileName()); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/MultipleProvidersForPluginException.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/MultipleProvidersForPluginException.java index 82a6ad9..cf38310 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/MultipleProvidersForPluginException.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/MultipleProvidersForPluginException.java
@@ -18,14 +18,14 @@ import com.google.common.base.Joiner; import com.google.common.collect.Iterables; -import java.io.File; +import java.nio.file.Path; class MultipleProvidersForPluginException extends IllegalArgumentException { private static final long serialVersionUID = 1L; - MultipleProvidersForPluginException(File pluginSrcFile, + MultipleProvidersForPluginException(Path pluginSrcPath, Iterable<ServerPluginProvider> providersHandlers) { - super(pluginSrcFile.getAbsolutePath() + super(pluginSrcPath.toAbsolutePath() + " is claimed to be handled by more than one plugin provider: " + providersListToString(providersHandlers)); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java index b227909..6b84c21 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/Plugin.java
@@ -14,6 +14,8 @@ package com.google.gerrit.server.plugins; +import static com.google.gerrit.common.FileUtil.lastModified; + import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.gerrit.common.Nullable; @@ -25,7 +27,7 @@ import org.eclipse.jgit.internal.storage.file.FileSnapshot; -import java.io.File; +import java.nio.file.Path; import java.util.Collections; import java.util.List; import java.util.jar.Attributes; @@ -67,7 +69,7 @@ } private final String name; - private final File srcFile; + private final Path srcFile; private final ApiType apiType; private final boolean disabled; private final CacheKey cacheKey; @@ -80,17 +82,17 @@ private List<ReloadableRegistrationHandle<?>> reloadableHandles; public Plugin(String name, - File srcFile, + Path srcPath, PluginUser pluginUser, FileSnapshot snapshot, ApiType apiType) { this.name = name; - this.srcFile = srcFile; + this.srcFile = srcPath; this.apiType = apiType; this.snapshot = snapshot; this.pluginUser = pluginUser; this.cacheKey = new Plugin.CacheKey(name); - this.disabled = srcFile.getName().endsWith(".disabled"); + this.disabled = srcPath.getFileName().toString().endsWith(".disabled"); } public CleanupHandle getCleanupHandle() { @@ -105,7 +107,7 @@ return pluginUser; } - public File getSrcFile() { + public Path getSrcFile() { return srcFile; } @@ -168,7 +170,7 @@ abstract boolean canReload(); - boolean isModified(File jar) { - return snapshot.lastModified() != jar.lastModified(); + boolean isModified(Path jar) { + return snapshot.lastModified() != lastModified(jar); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginContentScanner.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginContentScanner.java index 0228509..1d9cd0e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginContentScanner.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginContentScanner.java
@@ -11,14 +11,15 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + package com.google.gerrit.server.plugins; import com.google.common.base.Optional; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; +import java.nio.file.NoSuchFileException; import java.util.Collections; import java.util.Enumeration; import java.util.Map; @@ -57,7 +58,7 @@ @Override public InputStream getInputStream(PluginEntry entry) throws IOException { - throw new FileNotFoundException("Empty plugin"); + throw new NoSuchFileException("Empty plugin"); } @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java index b51359d..56233f0 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java
@@ -18,6 +18,8 @@ import com.google.common.base.Joiner; import com.google.common.base.MoreObjects; import com.google.common.base.Predicate; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Lists; @@ -25,6 +27,7 @@ import com.google.common.collect.Multimap; import com.google.common.collect.Queues; import com.google.common.collect.Sets; +import com.google.common.io.ByteStreams; import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.extensions.systemstatus.ServerInformation; @@ -45,14 +48,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileFilter; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.AbstractMap; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -71,13 +75,13 @@ static final String PLUGIN_TMP_PREFIX = "plugin_"; static final Logger log = LoggerFactory.getLogger(PluginLoader.class); - public String getPluginName(File srcFile) { - return MoreObjects.firstNonNull(getGerritPluginName(srcFile), - nameOf(srcFile)); + public String getPluginName(Path srcPath) { + return MoreObjects.firstNonNull(getGerritPluginName(srcPath), + nameOf(srcPath)); } - private final File pluginsDir; - private final File dataDir; + private final Path pluginsDir; + private final Path dataDir; private final PluginGuiceEnvironment env; private final ServerInformationImpl srvInfoImpl; private final PluginUser.Factory pluginUserFactory; @@ -158,7 +162,7 @@ checkRemoteInstall(); String fileName = originalName; - File tmp = asTemp(in, ".next_" + fileName + "_", ".tmp", pluginsDir); + Path tmp = asTemp(in, ".next_" + fileName + "_", ".tmp", pluginsDir); String name = MoreObjects.firstNonNull(getGerritPluginName(tmp), nameOf(fileName)); if (!originalName.equals(name)) { @@ -168,26 +172,26 @@ } String fileExtension = getExtension(fileName); - File dst = new File(pluginsDir, name + fileExtension); + Path dst = pluginsDir.resolve(name + fileExtension); synchronized (this) { Plugin active = running.get(name); if (active != null) { - fileName = active.getSrcFile().getName(); + fileName = active.getSrcFile().getFileName().toString(); log.info(String.format("Replacing plugin %s", active.getName())); - File old = new File(pluginsDir, ".last_" + fileName); - old.delete(); - active.getSrcFile().renameTo(old); + Path old = pluginsDir.resolve(".last_" + fileName); + Files.deleteIfExists(old); + Files.move(active.getSrcFile(), old); } - new File(pluginsDir, fileName + ".disabled").delete(); - tmp.renameTo(dst); + Files.deleteIfExists(pluginsDir.resolve(fileName + ".disabled")); + Files.move(tmp, dst); try { Plugin plugin = runPlugin(name, dst, active); if (active == null) { log.info(String.format("Installed plugin %s", plugin.getName())); } } catch (PluginInstallException e) { - dst.delete(); + Files.deleteIfExists(dst); throw e; } @@ -195,21 +199,17 @@ } } - static File asTemp(InputStream in, String prefix, String suffix, File dir) + static Path asTemp(InputStream in, String prefix, String suffix, Path dir) throws IOException { - File tmp = File.createTempFile(prefix, suffix, dir); + Path tmp = Files.createTempFile(dir, prefix, suffix); boolean keep = false; - try (FileOutputStream out = new FileOutputStream(tmp)) { - byte[] data = new byte[8192]; - int n; - while ((n = in.read(data)) > 0) { - out.write(data, 0, n); - } + try (OutputStream out = Files.newOutputStream(tmp)) { + ByteStreams.copy(in, out); keep = true; return tmp; } finally { if (!keep) { - tmp.delete(); + Files.delete(tmp); } } } @@ -240,12 +240,21 @@ } log.info(String.format("Disabling plugin %s", active.getName())); - File off = new File(active.getSrcFile() + ".disabled"); - active.getSrcFile().renameTo(off); + Path off = active.getSrcFile().resolveSibling( + active.getSrcFile().getFileName() + ".disabled"); + try { + Files.move(active.getSrcFile(), off); + } catch (IOException e) { + log.error("Failed to disable plugin", e); + // In theory we could still unload the plugin even if the rename + // failed. However, it would be reloaded on the next server startup, + // which is probably not what the user expects. + continue; + } unloadPlugin(active); try { - FileSnapshot snapshot = FileSnapshot.save(off); + FileSnapshot snapshot = FileSnapshot.save(off.toFile()); Plugin offPlugin = loadPlugin(name, off, snapshot); disabled.put(name, offPlugin); } catch (Throwable e) { @@ -274,13 +283,17 @@ } log.info(String.format("Enabling plugin %s", name)); - String n = off.getSrcFile().getName(); + String n = off.getSrcFile().toFile().getName(); if (n.endsWith(".disabled")) { n = n.substring(0, n.lastIndexOf('.')); } - File on = new File(pluginsDir, n); - off.getSrcFile().renameTo(on); - + Path on = pluginsDir.resolve(n); + try { + Files.move(off.getSrcFile(), on); + } catch (IOException e) { + log.error("Failed to move plugin " + name + " into place", e); + continue; + } disabled.remove(name); runPlugin(name, on, null); } @@ -290,7 +303,7 @@ @Override public synchronized void start() { - log.info("Loading plugins from " + pluginsDir.getAbsolutePath()); + log.info("Loading plugins from " + pluginsDir.toAbsolutePath()); srvInfoImpl.state = ServerInformation.State.STARTUP; rescan(); srvInfoImpl.state = ServerInformation.State.RUNNING; @@ -354,30 +367,30 @@ } public synchronized void rescan() { - Multimap<String, File> pluginsFiles = prunePlugins(pluginsDir); + Multimap<String, Path> pluginsFiles = prunePlugins(pluginsDir); if (pluginsFiles.isEmpty()) { return; } syncDisabledPlugins(pluginsFiles); - Map<String, File> activePlugins = filterDisabled(pluginsFiles); - for (Map.Entry<String, File> entry : jarsFirstSortedPluginsSet(activePlugins)) { + Map<String, Path> activePlugins = filterDisabled(pluginsFiles); + for (Map.Entry<String, Path> entry : jarsFirstSortedPluginsSet(activePlugins)) { String name = entry.getKey(); - File file = entry.getValue(); - String fileName = file.getName(); - if (!isJsPlugin(fileName) && !serverPluginFactory.handles(file)) { + Path path = entry.getValue(); + String fileName = path.getFileName().toString(); + if (!isJsPlugin(fileName) && !serverPluginFactory.handles(path)) { log.warn("No Plugin provider was found that handles this file format: {}", fileName); continue; } FileSnapshot brokenTime = broken.get(name); - if (brokenTime != null && !brokenTime.isModified(file)) { + if (brokenTime != null && !brokenTime.isModified(path.toFile())) { continue; } Plugin active = running.get(name); - if (active != null && !active.isModified(file)) { + if (active != null && !active.isModified(path)) { continue; } @@ -387,7 +400,7 @@ } try { - Plugin loadedPlugin = runPlugin(name, file, active); + Plugin loadedPlugin = runPlugin(name, path, active); if (active == null && !loadedPlugin.isDisabled()) { log.info(String.format("Loaded plugin %s, version %s", loadedPlugin.getName(), loadedPlugin.getVersion())); @@ -400,31 +413,32 @@ cleanInBackground(); } - private void addAllEntries(Map<String, File> from, - TreeSet<Entry<String, File>> to) { - Iterator<Entry<String, File>> it = from.entrySet().iterator(); + private void addAllEntries(Map<String, Path> from, + TreeSet<Entry<String, Path>> to) { + Iterator<Entry<String, Path>> it = from.entrySet().iterator(); while (it.hasNext()) { - Entry<String,File> entry = it.next(); + Entry<String,Path> entry = it.next(); to.add(new AbstractMap.SimpleImmutableEntry<>( entry.getKey(), entry.getValue())); } } - private TreeSet<Entry<String, File>> jarsFirstSortedPluginsSet( - Map<String, File> activePlugins) { - TreeSet<Entry<String, File>> sortedPlugins = - Sets.newTreeSet(new Comparator<Entry<String, File>>() { + private TreeSet<Entry<String, Path>> jarsFirstSortedPluginsSet( + Map<String, Path> activePlugins) { + TreeSet<Entry<String, Path>> sortedPlugins = + Sets.newTreeSet(new Comparator<Entry<String, Path>>() { @Override - public int compare(Entry<String, File> entry1, - Entry<String, File> entry2) { - String file1 = entry1.getValue().getName(); - String file2 = entry2.getValue().getName(); - int cmp = file1.compareTo(file2); - if (file1.endsWith(".jar")) { - return (file2.endsWith(".jar") ? cmp : -1); - } else { - return (file2.endsWith(".jar") ? +1 : cmp); - } + public int compare(Entry<String, Path> e1, Entry<String, Path> e2) { + Path n1 = e1.getValue().getFileName(); + Path n2 = e2.getValue().getFileName(); + return ComparisonChain.start() + .compareTrueFirst(isJar(n1), isJar(n2)) + .compare(n1, n2) + .result(); + } + + private boolean isJar(Path n1) { + return n1.toString().endsWith(".jar"); } }); @@ -432,14 +446,14 @@ return sortedPlugins; } - private void syncDisabledPlugins(Multimap<String, File> jars) { + private void syncDisabledPlugins(Multimap<String, Path> jars) { stopRemovedPlugins(jars); dropRemovedDisabledPlugins(jars); } - private Plugin runPlugin(String name, File plugin, Plugin oldPlugin) + private Plugin runPlugin(String name, Path plugin, Plugin oldPlugin) throws PluginInstallException { - FileSnapshot snapshot = FileSnapshot.save(plugin); + FileSnapshot snapshot = FileSnapshot.save(plugin.toFile()); try { Plugin newPlugin = loadPlugin(name, plugin, snapshot); if (newPlugin.getCleanupHandle() != null) { @@ -479,11 +493,11 @@ } } - private void stopRemovedPlugins(Multimap<String, File> jars) { + private void stopRemovedPlugins(Multimap<String, Path> jars) { Set<String> unload = Sets.newHashSet(running.keySet()); - for (Map.Entry<String, Collection<File>> entry : jars.asMap().entrySet()) { - for (File file : entry.getValue()) { - if (!file.getName().endsWith(".disabled")) { + for (Map.Entry<String, Collection<Path>> entry : jars.asMap().entrySet()) { + for (Path path : entry.getValue()) { + if (!path.getFileName().toString().endsWith(".disabled")) { unload.remove(entry.getKey()); } } @@ -493,11 +507,11 @@ } } - private void dropRemovedDisabledPlugins(Multimap<String, File> jars) { + private void dropRemovedDisabledPlugins(Multimap<String, Path> jars) { Set<String> unload = Sets.newHashSet(disabled.keySet()); - for (Map.Entry<String, Collection<File>> entry : jars.asMap().entrySet()) { - for (File file : entry.getValue()) { - if (file.getName().endsWith(".disabled")) { + for (Map.Entry<String, Collection<Path>> entry : jars.asMap().entrySet()) { + for (Path path : entry.getValue()) { + if (path.getFileName().toString().endsWith(".disabled")) { unload.remove(entry.getKey()); } } @@ -528,8 +542,8 @@ } } - public static String nameOf(File plugin) { - return nameOf(plugin.getName()); + public static String nameOf(Path plugin) { + return nameOf(plugin.getFileName().toString()); } private static String nameOf(String name) { @@ -545,21 +559,21 @@ return 0 < ext ? name.substring(ext) : ""; } - private Plugin loadPlugin(String name, File srcPlugin, FileSnapshot snapshot) + private Plugin loadPlugin(String name, Path srcPlugin, FileSnapshot snapshot) throws InvalidPluginException { - String pluginName = srcPlugin.getName(); + String pluginName = srcPlugin.getFileName().toString(); if (isJsPlugin(pluginName)) { return loadJsPlugin(name, srcPlugin, snapshot); } else if (serverPluginFactory.handles(srcPlugin)) { return loadServerPlugin(srcPlugin, snapshot); } else { throw new InvalidPluginException(String.format( - "Unsupported plugin type: %s", srcPlugin.getName())); + "Unsupported plugin type: %s", srcPlugin.getFileName())); } } - private File getPluginDataDir(String name) { - return new File(dataDir, name); + private Path getPluginDataDir(String name) { + return dataDir.resolve(name); } private String getPluginCanonicalWebUrl(String name) { @@ -569,11 +583,11 @@ return url; } - private Plugin loadJsPlugin(String name, File srcJar, FileSnapshot snapshot) { + private Plugin loadJsPlugin(String name, Path srcJar, FileSnapshot snapshot) { return new JsPlugin(name, srcJar, pluginUserFactory.create(name), snapshot); } - private ServerPlugin loadServerPlugin(File scriptFile, + private ServerPlugin loadServerPlugin(Path scriptFile, FileSnapshot snapshot) throws InvalidPluginException { String name = serverPluginFactory.getPluginName(scriptFile); return serverPluginFactory.get(scriptFile, snapshot, new PluginDescription( @@ -597,15 +611,15 @@ // Only one active plugin per plugin name can exist for each plugin name. // Filter out disabled plugins and transform the multimap to a map - private static Map<String, File> filterDisabled( - Multimap<String, File> pluginFiles) { - Map<String, File> activePlugins = Maps.newHashMapWithExpectedSize( - pluginFiles.keys().size()); - for (String name : pluginFiles.keys()) { - for (File pluginFile : pluginFiles.asMap().get(name)) { - if (!pluginFile.getName().endsWith(".disabled")) { + private static Map<String, Path> filterDisabled( + Multimap<String, Path> pluginPaths) { + Map<String, Path> activePlugins = Maps.newHashMapWithExpectedSize( + pluginPaths.keys().size()); + for (String name : pluginPaths.keys()) { + for (Path pluginPath : pluginPaths.asMap().get(name)) { + if (!pluginPath.getFileName().toString().endsWith(".disabled")) { assert(!activePlugins.containsKey(name)); - activePlugins.put(name, pluginFile); + activePlugins.put(name, pluginPath); } } } @@ -621,37 +635,40 @@ // // NOTE: Bear in mind that the plugin name can be reassigned after load by the // Server plugin provider. - public Multimap<String, File> prunePlugins(File pluginsDir) { - List<File> pluginFiles = scanFilesInPluginsDirectory(pluginsDir); - Multimap<String, File> map; - map = asMultimap(pluginFiles); + public Multimap<String, Path> prunePlugins(Path pluginsDir) { + List<Path> pluginPaths = scanPathsInPluginsDirectory(pluginsDir); + Multimap<String, Path> map; + map = asMultimap(pluginPaths); for (String plugin : map.keySet()) { - Collection<File> files = map.asMap().get(plugin); + Collection<Path> files = map.asMap().get(plugin); if (files.size() == 1) { continue; } // retrieve enabled plugins - Iterable<File> enabled = filterDisabledPlugins( - files); + Iterable<Path> enabled = filterDisabledPlugins(files); // If we have only one (the winner) plugin, nothing to do if (!Iterables.skip(enabled, 1).iterator().hasNext()) { continue; } - File winner = Iterables.getFirst(enabled, null); + Path winner = Iterables.getFirst(enabled, null); assert(winner != null); // Disable all loser plugins by renaming their file names to // "file.disabled" and replace the disabled files in the multimap. - Collection<File> elementsToRemove = Lists.newArrayList(); - Collection<File> elementsToAdd = Lists.newArrayList(); - for (File loser : Iterables.skip(enabled, 1)) { + Collection<Path> elementsToRemove = Lists.newArrayList(); + Collection<Path> elementsToAdd = Lists.newArrayList(); + for (Path loser : Iterables.skip(enabled, 1)) { log.warn(String.format("Plugin <%s> was disabled, because" + " another plugin <%s>" + " with the same name <%s> already exists", loser, winner, plugin)); - File disabledPlugin = new File(loser + ".disabled"); + Path disabledPlugin = Paths.get(loser + ".disabled"); elementsToAdd.add(disabledPlugin); elementsToRemove.add(loser); - loser.renameTo(disabledPlugin); + try { + Files.move(loser, disabledPlugin); + } catch (IOException e) { + log.warn("Failed to fully disable plugin " + loser, e); + } } Iterables.removeAll(files, elementsToRemove); Iterables.addAll(files, elementsToAdd); @@ -659,50 +676,52 @@ return map; } - private List<File> scanFilesInPluginsDirectory(File pluginsDir) { - if (pluginsDir == null || !pluginsDir.exists()) { + private List<Path> scanPathsInPluginsDirectory(Path pluginsDir) { + if (pluginsDir == null || !Files.exists(pluginsDir)) { return Collections.emptyList(); } - File[] matches = pluginsDir.listFiles(new FileFilter() { + DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() { @Override - public boolean accept(File pathname) { - String n = pathname.getName(); + public boolean accept(Path entry) throws IOException { + String n = entry.getFileName().toString(); return !n.startsWith(".last_") && !n.startsWith(".next_"); } - }); - if (matches == null) { - log.error("Cannot list " + pluginsDir.getAbsolutePath()); - return Collections.emptyList(); + }; + try (DirectoryStream<Path> files + = Files.newDirectoryStream(pluginsDir, filter)) { + return ImmutableList.copyOf(files); + } catch (IOException e) { + log.error("Cannot list " + pluginsDir.toAbsolutePath(), e); + return ImmutableList.of(); } - return Arrays.asList(matches); } - private static Iterable<File> filterDisabledPlugins( - Collection<File> files) { - return Iterables.filter(files, new Predicate<File>() { + private static Iterable<Path> filterDisabledPlugins( + Collection<Path> paths) { + return Iterables.filter(paths, new Predicate<Path>() { @Override - public boolean apply(File file) { - return !file.getName().endsWith(".disabled"); + public boolean apply(Path p) { + return !p.getFileName().toString().endsWith(".disabled"); } }); } - public String getGerritPluginName(File srcFile) { - String fileName = srcFile.getName(); + public String getGerritPluginName(Path srcPath) { + String fileName = srcPath.getFileName().toString(); if (isJsPlugin(fileName)) { return fileName.substring(0, fileName.length() - 3); } - if (serverPluginFactory.handles(srcFile)) { - return serverPluginFactory.getPluginName(srcFile); + if (serverPluginFactory.handles(srcPath)) { + return serverPluginFactory.getPluginName(srcPath); } return null; } - private Multimap<String, File> asMultimap(List<File> plugins) { - Multimap<String, File> map = LinkedHashMultimap.create(); - for (File srcFile : plugins) { - map.put(getPluginName(srcFile), srcFile); + private Multimap<String, Path> asMultimap(List<Path> plugins) { + Multimap<String, Path> map = LinkedHashMultimap.create(); + for (Path srcPath : plugins) { + map.put(getPluginName(srcPath), srcPath); } return map; }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPlugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPlugin.java index 0b037fb..28d57b2 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPlugin.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPlugin.java
@@ -17,25 +17,19 @@ import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.gerrit.common.Nullable; -import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl; -import com.google.gerrit.extensions.annotations.PluginData; -import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.extensions.registration.RegistrationHandle; import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle; import com.google.gerrit.lifecycle.LifecycleManager; import com.google.gerrit.server.PluginUser; import com.google.gerrit.server.util.RequestContext; -import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; -import com.google.inject.Provider; -import com.google.inject.ProvisionException; import org.eclipse.jgit.internal.storage.file.FileSnapshot; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.List; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -59,7 +53,7 @@ private final Manifest manifest; private final PluginContentScanner scanner; - private final File dataDir; + private final Path dataDir; private final String pluginCanonicalWebUrl; private final ClassLoader classLoader; private Class<? extends Module> sysModule; @@ -75,12 +69,13 @@ public ServerPlugin(String name, String pluginCanonicalWebUrl, PluginUser pluginUser, - File srcJar, + Path srcJar, FileSnapshot snapshot, PluginContentScanner scanner, - File dataDir, + Path dataDir, ClassLoader classLoader) throws InvalidPluginException { - super(name, srcJar, pluginUser, snapshot, Plugin.getApiType(getPluginManifest(scanner))); + super(name, srcJar, pluginUser, snapshot, + Plugin.getApiType(getPluginManifest(scanner))); this.pluginCanonicalWebUrl = pluginCanonicalWebUrl; this.scanner = scanner; this.dataDir = dataDir; @@ -127,10 +122,18 @@ return (Class<? extends Module>) clazz; } - File getSrcJar() { + Path getSrcJar() { return getSrcFile(); } + Path getDataDir() { + return dataDir; + } + + String getPluginCanonicalWebUrl() { + return pluginCanonicalWebUrl; + } + private static Manifest getPluginManifest(PluginContentScanner scanner) throws InvalidPluginException { try { @@ -229,45 +232,11 @@ } private Injector newRootInjector(final PluginGuiceEnvironment env) { - List<Module> modules = Lists.newArrayListWithCapacity(4); + List<Module> modules = Lists.newArrayListWithCapacity(2); if (getApiType() == ApiType.PLUGIN) { modules.add(env.getSysModule()); } - modules.add(new AbstractModule() { - @Override - protected void configure() { - bind(PluginUser.class).toInstance(getPluginUser()); - bind(String.class) - .annotatedWith(PluginName.class) - .toInstance(getName()); - bind(String.class) - .annotatedWith(PluginCanonicalWebUrl.class) - .toInstance(pluginCanonicalWebUrl); - - bind(File.class) - .annotatedWith(PluginData.class) - .toProvider(new Provider<File>() { - private volatile boolean ready; - - @Override - public File get() { - if (!ready) { - synchronized (dataDir) { - if (!ready) { - if (!dataDir.exists() && !dataDir.mkdirs()) { - throw new ProvisionException(String.format( - "Cannot create %s for plugin %s", - dataDir.getAbsolutePath(), getName())); - } - ready = true; - } - } - } - return dataDir; - } - }); - } - }); + modules.add(new ServerPluginInfoModule(this)); return Guice.createInjector(modules); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginInfoModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginInfoModule.java new file mode 100644 index 0000000..b0e9453 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginInfoModule.java
@@ -0,0 +1,77 @@ +// Copyright (C) 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.server.plugins; + +import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl; +import com.google.gerrit.extensions.annotations.PluginData; +import com.google.gerrit.extensions.annotations.PluginName; +import com.google.gerrit.server.PluginUser; +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.ProvisionException; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +class ServerPluginInfoModule extends AbstractModule { + private final ServerPlugin plugin; + private final Path dataDir; + + private volatile boolean ready; + + ServerPluginInfoModule(ServerPlugin plugin) { + this.plugin = plugin; + this.dataDir = plugin.getDataDir(); + } + + @Override + protected void configure() { + bind(PluginUser.class).toInstance(plugin.getPluginUser()); + bind(String.class) + .annotatedWith(PluginName.class) + .toInstance(plugin.getName()); + bind(String.class) + .annotatedWith(PluginCanonicalWebUrl.class) + .toInstance(plugin.getPluginCanonicalWebUrl()); + } + + @Provides + @PluginData + Path getPluginData() { + if (!ready) { + synchronized (dataDir) { + if (!ready) { + try { + Files.createDirectories(dataDir); + } catch (IOException e) { + throw new ProvisionException(String.format( + "Cannot create %s for plugin %s", + dataDir.toAbsolutePath(), plugin.getName()), e); + } + ready = true; + } + } + } + return dataDir; + } + + @Provides + @PluginData + File getPluginDataAsFile(@PluginData Path pluginData) { + return pluginData.toFile(); + } +}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginProvider.java index 37fed9b..bc2432b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginProvider.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ServerPluginProvider.java
@@ -19,7 +19,7 @@ import org.eclipse.jgit.internal.storage.file.FileSnapshot; -import java.io.File; +import java.nio.file.Path; /** * Provider of one Server plugin from one external file @@ -40,7 +40,7 @@ public class PluginDescription { public final PluginUser user; public final String canonicalUrl; - public final File dataDir; + public final Path dataDir; /** * Creates a new PluginDescription for ServerPluginProvider. @@ -49,7 +49,7 @@ * @param canonicalUrl plugin root Web URL * @param dataDir directory for plugin data */ - public PluginDescription(PluginUser user, String canonicalUrl, File dataDir) { + public PluginDescription(PluginUser user, String canonicalUrl, Path dataDir) { this.user = user; this.canonicalUrl = canonicalUrl; this.dataDir = dataDir; @@ -59,39 +59,39 @@ /** * Declares the availability to manage an external file or directory * - * @param srcFile the external file or directory + * @param srcPath the external file or directory * @return true if file or directory can be loaded into a Server Plugin */ - boolean handles(File srcFile); + boolean handles(Path srcPath); /** * Returns the plugin name of an external file or directory * - * Should be called only if {@link #handles(File) handles(srcFile)} + * Should be called only if {@link #handles(Path) handles(srcFile)} * returns true and thus srcFile is a supported plugin format. * An IllegalArgumentException is thrown otherwise as srcFile * is not a valid file format for extracting its plugin name. * - * @param srcFile external file or directory + * @param srcPath external file or directory * @return plugin name */ - String getPluginName(File srcFile); + String getPluginName(Path srcPath); /** * Loads an external file or directory into a Server plugin. * - * Should be called only if {@link #handles(File) handles(srcFile)} + * Should be called only if {@link #handles(Path) handles(srcFile)} * returns true and thus srcFile is a supported plugin format. * An IllegalArgumentException is thrown otherwise as srcFile * is not a valid file format for extracting its plugin name. * - * @param srcFile external file or directory + * @param srcPath external file or directory * @param snapshot snapshot of the external file * @param pluginDescriptor descriptor of the ServerPlugin to load * @throws InvalidPluginException if plugin is supposed to be handled * but cannot be loaded for any other reason */ - ServerPlugin get(File srcFile, FileSnapshot snapshot, + ServerPlugin get(Path srcPath, FileSnapshot snapshot, PluginDescription pluginDescriptor) throws InvalidPluginException; /**
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/UniversalServerPluginProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/UniversalServerPluginProvider.java index 0e8bd87..afdc5b3 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/UniversalServerPluginProvider.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/UniversalServerPluginProvider.java
@@ -22,7 +22,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -38,27 +38,26 @@ } @Override - public ServerPlugin get(File srcFile, FileSnapshot snapshot, + public ServerPlugin get(Path srcPath, FileSnapshot snapshot, PluginDescription pluginDescription) throws InvalidPluginException { - return providerOf(srcFile).get(srcFile, snapshot, pluginDescription); + return providerOf(srcPath).get(srcPath, snapshot, pluginDescription); } @Override - public String getPluginName(File srcFile) { - return providerOf(srcFile).getPluginName(srcFile); + public String getPluginName(Path srcPath) { + return providerOf(srcPath).getPluginName(srcPath); } @Override - public boolean handles(File srcFile) { - List<ServerPluginProvider> providers = - providersForHandlingPlugin(srcFile); + public boolean handles(Path srcPath) { + List<ServerPluginProvider> providers = providersForHandlingPlugin(srcPath); switch (providers.size()) { case 1: return true; case 0: return false; default: - throw new MultipleProvidersForPluginException(srcFile, providers); + throw new MultipleProvidersForPluginException(srcPath, providers); } } @@ -67,27 +66,27 @@ return "gerrit"; } - private ServerPluginProvider providerOf(File srcFile) { + private ServerPluginProvider providerOf(Path srcPath) { List<ServerPluginProvider> providers = - providersForHandlingPlugin(srcFile); + providersForHandlingPlugin(srcPath); switch (providers.size()) { case 1: return providers.get(0); case 0: throw new IllegalArgumentException( "No ServerPluginProvider found/loaded to handle plugin file " - + srcFile.getAbsolutePath()); + + srcPath.toAbsolutePath()); default: - throw new MultipleProvidersForPluginException(srcFile, providers); + throw new MultipleProvidersForPluginException(srcPath, providers); } } private List<ServerPluginProvider> providersForHandlingPlugin( - final File srcFile) { + final Path srcPath) { List<ServerPluginProvider> providers = new ArrayList<>(); for (ServerPluginProvider serverPluginProvider : serverPluginProviders) { - boolean handles = serverPluginProvider.handles(srcFile); - log.debug("File {} handled by {} ? => {}", srcFile, + boolean handles = serverPluginProvider.handles(srcPath); + log.debug("File {} handled by {} ? => {}", srcPath, serverPluginProvider.getProviderPluginName(), handles); if (handles) { providers.add(serverPluginProvider);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CommitsCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CommitsCollection.java index e5e7bed..4879bb7 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CommitsCollection.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CommitsCollection.java
@@ -65,26 +65,19 @@ throw new ResourceNotFoundException(id); } - Repository repo = repoManager.openRepository(parent.getNameKey()); - try { - RevWalk rw = new RevWalk(repo); - try { - RevCommit commit = rw.parseCommit(objectId); - rw.parseBody(commit); - if (!parent.getControl().canReadCommit(db.get(), rw, commit)) { - throw new ResourceNotFoundException(id); - } - for (int i = 0; i < commit.getParentCount(); i++) { - rw.parseBody(rw.parseCommit(commit.getParent(i))); - } - return new CommitResource(parent, commit); - } catch (MissingObjectException | IncorrectObjectTypeException e) { + try (Repository repo = repoManager.openRepository(parent.getNameKey()); + RevWalk rw = new RevWalk(repo)) { + RevCommit commit = rw.parseCommit(objectId); + rw.parseBody(commit); + if (!parent.getControl().canReadCommit(db.get(), rw, commit)) { throw new ResourceNotFoundException(id); - } finally { - rw.release(); } - } finally { - repo.close(); + for (int i = 0; i < commit.getParentCount(); i++) { + rw.parseBody(rw.parseCommit(commit.getParent(i))); + } + return new CommitResource(parent, commit); + } catch (MissingObjectException | IncorrectObjectTypeException e) { + throw new ResourceNotFoundException(id); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranches.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranches.java index bdc67ac..d6e93f0 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranches.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranches.java
@@ -99,11 +99,8 @@ for (String branch : input.branches) { batchUpdate.addCommand(createDeleteCommand(project, r, branch)); } - RevWalk rw = new RevWalk(r); - try { + try (RevWalk rw = new RevWalk(r)) { batchUpdate.execute(rw, NullProgressMonitor.INSTANCE); - } finally { - rw.release(); } StringBuilder errorMessages = new StringBuilder(); for (ReceiveCommand command : batchUpdate.getCommands()) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetHead.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetHead.java index 0530a4c..2efd257 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetHead.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetHead.java
@@ -49,9 +49,7 @@ @Override public String apply(ProjectResource rsrc) throws AuthException, ResourceNotFoundException, IOException { - Repository repo = null; - try { - repo = repoManager.openRepository(rsrc.getNameKey()); + try (Repository repo = repoManager.openRepository(rsrc.getNameKey())) { Ref head = repo.getRef(Constants.HEAD); if (head == null) { throw new ResourceNotFoundException(Constants.HEAD); @@ -62,8 +60,7 @@ } throw new AuthException("not allowed to see HEAD"); } else if (head.getObjectId() != null) { - RevWalk rw = new RevWalk(repo); - try { + try (RevWalk rw = new RevWalk(repo)) { RevCommit commit = rw.parseCommit(head.getObjectId()); if (rsrc.getControl().canReadCommit(db.get(), rw, commit)) { return head.getObjectId().name(); @@ -74,17 +71,11 @@ return head.getObjectId().name(); } throw new AuthException("not allowed to see HEAD"); - } finally { - rw.release(); } } throw new ResourceNotFoundException(Constants.HEAD); } catch (RepositoryNotFoundException e) { throw new ResourceNotFoundException(rsrc.getName()); - } finally { - if (repo != null) { - repo.close(); - } } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListDashboards.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListDashboards.java index 07fd095..456abfc 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListDashboards.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListDashboards.java
@@ -82,53 +82,45 @@ private List<DashboardInfo> scan(ProjectControl ctl, String project, boolean setDefault) throws ResourceNotFoundException, IOException { - Repository git; - try { - git = gitManager.openRepository(ctl.getProject().getNameKey()); + Project.NameKey projectName = ctl.getProject().getNameKey(); + try (Repository git = gitManager.openRepository(projectName); + RevWalk rw = new RevWalk(git)) { + List<DashboardInfo> all = Lists.newArrayList(); + for (Ref ref : git.getRefDatabase().getRefs(REFS_DASHBOARDS).values()) { + if (ctl.controlForRef(ref.getName()).canRead()) { + all.addAll(scanDashboards(ctl.getProject(), git, rw, ref, + project, setDefault)); + } + } + return all; } catch (RepositoryNotFoundException e) { throw new ResourceNotFoundException(); } - try { - RevWalk rw = new RevWalk(git); - try { - List<DashboardInfo> all = Lists.newArrayList(); - for (Ref ref : git.getRefDatabase().getRefs(REFS_DASHBOARDS).values()) { - if (ctl.controlForRef(ref.getName()).canRead()) { - all.addAll(scanDashboards(ctl.getProject(), git, rw, ref, - project, setDefault)); - } - } - return all; - } finally { - rw.release(); - } - } finally { - git.close(); - } } private List<DashboardInfo> scanDashboards(Project definingProject, Repository git, RevWalk rw, Ref ref, String project, boolean setDefault) throws IOException { List<DashboardInfo> list = Lists.newArrayList(); - TreeWalk tw = new TreeWalk(rw.getObjectReader()); - tw.addTree(rw.parseTree(ref.getObjectId())); - tw.setRecursive(true); - while (tw.next()) { - if (tw.getFileMode(0) == FileMode.REGULAR_FILE) { - try { - list.add(DashboardsCollection.parse( - definingProject, - ref.getName().substring(REFS_DASHBOARDS.length()), - tw.getPathString(), - new BlobBasedConfig(null, git, tw.getObjectId(0)), - project, - setDefault)); - } catch (ConfigInvalidException e) { - log.warn(String.format( - "Cannot parse dashboard %s:%s:%s: %s", - definingProject.getName(), ref.getName(), tw.getPathString(), - e.getMessage())); + try (TreeWalk tw = new TreeWalk(rw.getObjectReader())) { + tw.addTree(rw.parseTree(ref.getObjectId())); + tw.setRecursive(true); + while (tw.next()) { + if (tw.getFileMode(0) == FileMode.REGULAR_FILE) { + try { + list.add(DashboardsCollection.parse( + definingProject, + ref.getName().substring(REFS_DASHBOARDS.length()), + tw.getPathString(), + new BlobBasedConfig(null, git, tw.getObjectId(0)), + project, + setDefault)); + } catch (ConfigInvalidException e) { + log.warn(String.format( + "Cannot parse dashboard %s:%s:%s: %s", + definingProject.getName(), ref.getName(), tw.getPathString(), + e.getMessage())); + } } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java index e12b38a..b01e563 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java
@@ -98,26 +98,17 @@ public TagInfo get(ProjectResource resource, IdString id) throws ResourceNotFoundException, IOException { - Repository repo = getRepository(resource.getNameKey()); - - String tagName = id.get(); - if (!tagName.startsWith(Constants.R_TAGS)) { - tagName = Constants.R_TAGS + tagName; - } - - try { - RevWalk rw = new RevWalk(repo); - try { - Ref ref = repo.getRefDatabase().getRef(tagName); - if (ref != null && !visibleTags(resource.getControl(), repo, - ImmutableMap.of(ref.getName(), ref)).isEmpty()) { - return createTagInfo(ref, rw); - } - } finally { - rw.dispose(); + try (Repository repo = getRepository(resource.getNameKey()); + RevWalk rw = new RevWalk(repo)) { + String tagName = id.get(); + if (!tagName.startsWith(Constants.R_TAGS)) { + tagName = Constants.R_TAGS + tagName; } - } finally { - repo.close(); + Ref ref = repo.getRefDatabase().getRef(tagName); + if (ref != null && !visibleTags(resource.getControl(), repo, + ImmutableMap.of(ref.getName(), ref)).isEmpty()) { + return createTagInfo(ref, rw); + } } throw new ResourceNotFoundException(id); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PerformCreateProject.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PerformCreateProject.java index 03c954b..689920b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PerformCreateProject.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PerformCreateProject.java
@@ -270,8 +270,7 @@ private void createEmptyCommits(final Repository repo, final Project.NameKey project, final List<String> refs) throws IOException { - ObjectInserter oi = repo.newObjectInserter(); - try { + try (ObjectInserter oi = repo.newObjectInserter()) { CommitBuilder cb = new CommitBuilder(); cb.setTreeId(oi.insert(Constants.OBJ_TREE, new byte[] {})); cb.setAuthor(metaDataUpdateFactory.getUserPersonIdent()); @@ -300,8 +299,6 @@ "Cannot create empty commit for " + createProjectArgs.getProjectName(), e); throw e; - } finally { - oi.release(); } } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java index 558b572..e24e227 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
@@ -22,7 +22,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.io.Files; import com.google.gerrit.common.data.AccessSection; import com.google.gerrit.common.data.GroupReference; import com.google.gerrit.common.data.LabelType; @@ -55,9 +54,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -488,25 +488,25 @@ private ThemeInfo loadTheme() { String name = getConfig().getProject().getName(); - File dir = new File(sitePaths.themes_dir, name); - if (!dir.exists()) { + Path dir = sitePaths.themes_dir.resolve(name); + if (!Files.exists(dir)) { return ThemeInfo.INHERIT; - } else if (!dir.isDirectory()) { + } else if (!Files.isDirectory(dir)) { log.warn("Bad theme for {}: not a directory", name); return ThemeInfo.INHERIT; } try { - return new ThemeInfo(readFile(new File(dir, SitePaths.CSS_FILENAME)), - readFile(new File(dir, SitePaths.HEADER_FILENAME)), - readFile(new File(dir, SitePaths.FOOTER_FILENAME))); + return new ThemeInfo(readFile(dir.resolve(SitePaths.CSS_FILENAME)), + readFile(dir.resolve(SitePaths.HEADER_FILENAME)), + readFile(dir.resolve(SitePaths.FOOTER_FILENAME))); } catch (IOException e) { log.error("Error reading theme for " + name, e); return ThemeInfo.INHERIT; } } - private String readFile(File f) throws IOException { - return f.exists() ? Files.toString(f, UTF_8) : null; + private String readFile(Path p) throws IOException { + return Files.exists(p) ? new String(Files.readAllBytes(p), UTF_8) : null; } private boolean getInheritableBoolean(Function<Project, InheritableBoolean> func) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetHead.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetHead.java index 77c221c..ac21646 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetHead.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetHead.java
@@ -43,9 +43,9 @@ public class SetHead implements RestModifyView<ProjectResource, Input> { private static final Logger log = LoggerFactory.getLogger(SetHead.class); - static class Input { + public static class Input { @DefaultInput - String ref; + public String ref; } private final GitRepositoryManager repoManager;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java index f8279a0..a43247e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -523,18 +523,11 @@ return false; } String sha1 = ps.getRevision().get(); - Repository repo = repoManager.openRepository(change().getProject()); - try { - RevWalk walk = new RevWalk(repo); - try { - RevCommit c = walk.parseCommit(ObjectId.fromString(sha1)); - commitMessage = c.getFullMessage(); - commitFooters = c.getFooterLines(); - } finally { - walk.release(); - } - } finally { - repo.close(); + try (Repository repo = repoManager.openRepository(change().getProject()); + RevWalk walk = new RevWalk(repo)) { + RevCommit c = walk.parseCommit(ObjectId.fromString(sha1)); + commitMessage = c.getFullMessage(); + commitFooters = c.getFooterLines(); } return true; }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ConflictsPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ConflictsPredicate.java index 87c33a2..2070746 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ConflictsPredicate.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ConflictsPredicate.java
@@ -107,37 +107,24 @@ if (conflicts != null) { return conflicts; } - try { - Repository repo = + try (Repository repo = args.repoManager.openRepository(otherChange.getProject()); - try { - RevWalk rw = CodeReviewCommit.newRevWalk(repo); - try { - RevFlag canMergeFlag = rw.newFlag("CAN_MERGE"); - CodeReviewCommit commit = - (CodeReviewCommit) rw.parseCommit(changeDataCache.getTestAgainst()); - SubmitStrategy strategy = - args.submitStrategyFactory.create(submitType, - db.get(), repo, rw, null, canMergeFlag, - getAlreadyAccepted(repo, rw, commit), - otherChange.getDest()); - CodeReviewCommit otherCommit = - (CodeReviewCommit) rw.parseCommit(other); - otherCommit.add(canMergeFlag); - conflicts = !strategy.dryRun(commit, otherCommit); - args.conflictsCache.put(conflictsKey, conflicts); - return conflicts; - } catch (MergeException e) { - throw new IllegalStateException(e); - } catch (NoSuchProjectException e) { - throw new IllegalStateException(e); - } finally { - rw.release(); - } - } finally { - repo.close(); - } - } catch (IOException e) { + RevWalk rw = CodeReviewCommit.newRevWalk(repo)) { + RevFlag canMergeFlag = rw.newFlag("CAN_MERGE"); + CodeReviewCommit commit = + (CodeReviewCommit) rw.parseCommit(changeDataCache.getTestAgainst()); + SubmitStrategy strategy = + args.submitStrategyFactory.create(submitType, + db.get(), repo, rw, null, canMergeFlag, + getAlreadyAccepted(repo, rw, commit), + otherChange.getDest()); + CodeReviewCommit otherCommit = + (CodeReviewCommit) rw.parseCommit(other); + otherCommit.add(canMergeFlag); + conflicts = !strategy.dryRun(commit, otherCommit); + args.conflictsCache.put(conflictsKey, conflicts); + return conflicts; + } catch (MergeException | NoSuchProjectException | IOException e) { throw new IllegalStateException(e); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RevWalkPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RevWalkPredicate.java index fd57a44..0947fae 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RevWalkPredicate.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RevWalkPredicate.java
@@ -102,18 +102,9 @@ Arguments args = new Arguments(patchSet, revision, objectId, change, projectName); - try { - final Repository repo = repoManager.openRepository(projectName); - try { - final RevWalk rw = new RevWalk(repo); - try { - return match(repo, rw, args); - } finally { - rw.release(); - } - } finally { - repo.close(); - } + try (Repository repo = repoManager.openRepository(projectName); + RevWalk rw = new RevWalk(repo)) { + return match(repo, rw, args); } catch (RepositoryNotFoundException e) { log.error("Repository \"" + projectName.get() + "\" unknown.", e); } catch (IOException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/H2.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/H2.java index f43530f..66f2f1d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/H2.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/H2.java
@@ -20,9 +20,6 @@ import org.eclipse.jgit.lib.Config; -import java.io.File; -import java.io.IOException; - class H2 extends BaseDataSourceType { protected final Config cfg; @@ -41,12 +38,6 @@ if (database == null || database.isEmpty()) { database = "db/ReviewDB"; } - File db = site.resolve(database); - try { - db = db.getCanonicalFile(); - } catch (IOException e) { - db = db.getAbsoluteFile(); - } - return "jdbc:h2:" + db.toURI().toString(); + return "jdbc:h2:" + site.resolve(database).toUri().toString(); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java index daf1d4d..98e3937 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java
@@ -32,14 +32,14 @@ import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.lib.PersonIdent; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.Collections; /** Creates the current database schema and populates initial code rows. */ public class SchemaCreator { private final @SitePath - File site_path; + Path site_path; private final AllProjectsCreator allProjectsCreator; private final AllUsersCreator allUsersCreator; @@ -58,7 +58,7 @@ this(site.site_path, ap, auc, au, dst); } - public SchemaCreator(@SitePath File site, + public SchemaCreator(@SitePath Path site, AllProjectsCreator ap, AllUsersCreator auc, @GerritPersonIdent PersonIdent au, @@ -117,9 +117,9 @@ final SystemConfig s = SystemConfig.create(); try { - s.sitePath = site_path.getCanonicalPath(); + s.sitePath = site_path.toRealPath().normalize().toString(); } catch (IOException e) { - s.sitePath = site_path.getAbsolutePath(); + s.sitePath = site_path.toAbsolutePath().normalize().toString(); } c.systemConfig().insert(Collections.singleton(s)); return s;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java index 2b9d4b4..fe5b992 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java
@@ -131,9 +131,9 @@ throw new OrmException("No record in system_config table"); } try { - sc.sitePath = site.site_path.getCanonicalPath(); + sc.sitePath = site.site_path.toRealPath().normalize().toString(); } catch (IOException e) { - sc.sitePath = site.site_path.getAbsolutePath(); + sc.sitePath = site.site_path.toAbsolutePath().normalize().toString(); } db.systemConfig().update(Collections.singleton(sc)); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java index 591601d..c809af4 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java
@@ -58,14 +58,14 @@ throw new ProvisionException("Schema not yet initialized." + " Run init to initialize the schema:\n" + "$ java -jar gerrit.war init -d " - + site.site_path.getAbsolutePath()); + + site.site_path.toAbsolutePath()); } if (currentVer.versionNbr < expectedVer) { throw new ProvisionException("Unsupported schema version " + currentVer.versionNbr + "; expected schema version " + expectedVer + ". Run init to upgrade:\n" - + "$ java -jar " + site.gerrit_war.getAbsolutePath() + " init -d " - + site.site_path.getAbsolutePath()); + + "$ java -jar " + site.gerrit_war.toAbsolutePath() + " init -d " + + site.site_path.toAbsolutePath()); } else if (currentVer.versionNbr > expectedVer) { throw new ProvisionException("Unsupported schema version " + currentVer.versionNbr + "; expected schema version " + expectedVer
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/DefaultSecureStore.java b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/DefaultSecureStore.java index b852217..7665c64 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/DefaultSecureStore.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/DefaultSecureStore.java
@@ -26,6 +26,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -35,8 +36,8 @@ @Inject DefaultSecureStore(SitePaths site) { - File secureConfig = new File(site.etc_dir, "secure.config"); - sec = new FileBasedConfig(secureConfig, FS.DETECTED); + Path secureConfig = site.etc_dir.resolve("secure.config"); + sec = new FileBasedConfig(secureConfig.toFile(), FS.DETECTED); try { sec.load(); } catch (Exception e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreProvider.java index e830590..99127d8 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreProvider.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreProvider.java
@@ -26,14 +26,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; +import java.nio.file.Path; @Singleton public class SecureStoreProvider implements Provider<SecureStore> { private static final Logger log = LoggerFactory .getLogger(SecureStoreProvider.class); - private final File libdir; + private final Path libdir; private final Injector injector; private final String className;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/SystemLog.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/SystemLog.java index ba31f56..d4b8457 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/util/SystemLog.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/SystemLog.java
@@ -33,8 +33,8 @@ import org.eclipse.jgit.lib.Config; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; @Singleton public class SystemLog { @@ -55,12 +55,12 @@ return Strings.isNullOrEmpty(System.getProperty(LOG4J_CONFIGURATION)); } - public static Appender createAppender(File logdir, String name, Layout layout) { + public static Appender createAppender(Path logdir, String name, Layout layout) { final DailyRollingFileAppender dst = new DailyRollingFileAppender(); dst.setName(name); dst.setLayout(layout); dst.setEncoding("UTF-8"); - dst.setFile(new File(resolve(logdir), name).getPath()); + dst.setFile(resolve(logdir).resolve(name).toString()); dst.setImmediateFlush(true); dst.setAppend(true); dst.setErrorHandler(new DieErrorHandler()); @@ -90,11 +90,11 @@ return async; } - private static File resolve(final File logs_dir) { + private static Path resolve(Path p) { try { - return logs_dir.getCanonicalFile(); + return p.toRealPath().normalize(); } catch (IOException e) { - return logs_dir.getAbsoluteFile(); + return p.toAbsolutePath().normalize(); } }
diff --git a/gerrit-server/src/main/java/gerrit/PRED_commit_edits_2.java b/gerrit-server/src/main/java/gerrit/PRED_commit_edits_2.java index 2c7949c..509faf0 100644 --- a/gerrit-server/src/main/java/gerrit/PRED_commit_edits_2.java +++ b/gerrit-server/src/main/java/gerrit/PRED_commit_edits_2.java
@@ -73,11 +73,10 @@ PatchList pl = StoredValues.PATCH_LIST.get(engine); Repository repo = StoredValues.REPOSITORY.get(engine); - final ObjectReader reader = repo.newObjectReader(); - final RevTree aTree; - final RevTree bTree; - try { - final RevWalk rw = new RevWalk(reader); + try (ObjectReader reader = repo.newObjectReader(); + RevWalk rw = new RevWalk(reader)) { + final RevTree aTree; + final RevTree bTree; final RevCommit bCommit = rw.parseCommit(pl.getNewId()); if (pl.getOldId() != null) { @@ -129,8 +128,6 @@ } } catch (IOException err) { throw new JavaException(this, 1, err); - } finally { - reader.release(); } return engine.fail(); @@ -161,4 +158,4 @@ } return new Text(reader.open(tw.getObjectId(0), Constants.OBJ_BLOB)); } -} \ No newline at end of file +}
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/change/IncludedInResolverTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/change/IncludedInResolverTest.java index dc9724c..4cd31ab 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/change/IncludedInResolverTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/change/IncludedInResolverTest.java
@@ -86,6 +86,8 @@ */ + // TODO(dborowitz): Use try/finally when this doesn't double-close the repo. + @SuppressWarnings("resource") Git git = new Git(db); revWalk = new RevWalk(db); // Version 1.0 @@ -129,7 +131,7 @@ @Override @After public void tearDown() throws Exception { - revWalk.release(); + revWalk.close(); super.tearDown(); }
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/config/SitePathsTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/config/SitePathsTest.java index 5fdecf0..5533d53 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/config/SitePathsTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/config/SitePathsTest.java
@@ -25,88 +25,89 @@ import org.junit.Test; -import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NotDirectoryException; +import java.nio.file.Path; +import java.nio.file.Paths; public class SitePathsTest { @Test public void testCreate_NotExisting() throws IOException { - final File root = random(); + final Path root = random(); final SitePaths site = new SitePaths(root); assertTrue(site.isNew); assertEquals(root, site.site_path); - assertEquals(new File(root, "etc"), site.etc_dir); + assertEquals(root.resolve("etc"), site.etc_dir); } @Test public void testCreate_Empty() throws IOException { - final File root = random(); + final Path root = random(); try { - assertTrue(root.mkdir()); + Files.createDirectory(root); final SitePaths site = new SitePaths(root); assertTrue(site.isNew); assertEquals(root, site.site_path); } finally { - root.delete(); + Files.delete(root); } } @Test public void testCreate_NonEmpty() throws IOException { - final File root = random(); - final File txt = new File(root, "test.txt"); + final Path root = random(); + final Path txt = root.resolve("test.txt"); try { - assertTrue(root.mkdir()); - assertTrue(txt.createNewFile()); + Files.createDirectory(root); + Files.createFile(txt); final SitePaths site = new SitePaths(root); assertFalse(site.isNew); assertEquals(root, site.site_path); } finally { - txt.delete(); - root.delete(); + Files.delete(txt); + Files.delete(root); } } @Test public void testCreate_NotDirectory() throws IOException { - final File root = random(); + final Path root = random(); try { - assertTrue(root.createNewFile()); + Files.createFile(root); try { new SitePaths(root); fail("Did not throw exception"); - } catch (FileNotFoundException e) { - assertEquals("Not a directory: " + root.getPath(), e.getMessage()); + } catch (NotDirectoryException e) { + // Expected. } } finally { - root.delete(); + Files.delete(root); } } @Test public void testResolve() throws IOException { - final File root = random(); + final Path root = random(); final SitePaths site = new SitePaths(root); assertNull(site.resolve(null)); assertNull(site.resolve("")); assertNotNull(site.resolve("a")); - assertEquals(new File(root, "a").getCanonicalFile(), site.resolve("a")); + assertEquals(root.resolve("a").toAbsolutePath().normalize(), + site.resolve("a")); final String pfx = HostPlatform.isWin32() ? "C:/" : "/"; assertNotNull(site.resolve(pfx + "a")); - assertEquals(new File(pfx + "a").getCanonicalFile(), site.resolve(pfx + "a")); + assertEquals(Paths.get(pfx + "a"), site.resolve(pfx + "a")); } - private static File random() throws IOException { - File tmp = File.createTempFile("gerrit_test_", "_site"); - if (!tmp.delete()) { - throw new IOException("Cannot create " + tmp.getPath()); - } + private static Path random() throws IOException { + Path tmp = Files.createTempFile("gerrit_test_", "_site"); + Files.deleteIfExists(tmp); return tmp; } }
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java index f4f989f..c2f3f6f 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java
@@ -118,34 +118,37 @@ public void testEmptyCommit() throws Exception { expect(schemaFactory.open()).andReturn(schema); - final Repository realDb = createWorkRepository(); - final Git git = new Git(realDb); + try (Repository realDb = createWorkRepository()) { + // TODO(dborowitz): Use try/finally when this doesn't double-close the repo. + @SuppressWarnings("resource") + final Git git = new Git(realDb); - final RevCommit mergeTip = git.commit().setMessage("test").call(); + final RevCommit mergeTip = git.commit().setMessage("test").call(); - final Branch.NameKey branchNameKey = - new Branch.NameKey(new Project.NameKey("test-project"), "test-branch"); + final Branch.NameKey branchNameKey = + new Branch.NameKey(new Project.NameKey("test-project"), "test-branch"); - expect(urlProvider.get()).andReturn("http://localhost:8080"); + expect(urlProvider.get()).andReturn("http://localhost:8080"); - expect(schema.submoduleSubscriptions()).andReturn(subscriptions); - final ResultSet<SubmoduleSubscription> emptySubscriptions = - new ListResultSet<>(new ArrayList<SubmoduleSubscription>()); - expect(subscriptions.bySubmodule(branchNameKey)).andReturn( - emptySubscriptions); + expect(schema.submoduleSubscriptions()).andReturn(subscriptions); + final ResultSet<SubmoduleSubscription> emptySubscriptions = + new ListResultSet<>(new ArrayList<SubmoduleSubscription>()); + expect(subscriptions.bySubmodule(branchNameKey)).andReturn( + emptySubscriptions); - schema.close(); + schema.close(); - doReplay(); + doReplay(); - final SubmoduleOp submoduleOp = - new SubmoduleOp(branchNameKey, mergeTip, new RevWalk(realDb), urlProvider, - schemaFactory, realDb, null, new ArrayList<Change>(), null, null, - null, null, null, null); + final SubmoduleOp submoduleOp = + new SubmoduleOp(branchNameKey, mergeTip, new RevWalk(realDb), urlProvider, + schemaFactory, realDb, null, new ArrayList<Change>(), null, null, + null, null, null, null); - submoduleOp.update(); + submoduleOp.update(); - doVerify(); + doVerify(); + } } /** @@ -588,85 +591,89 @@ public void testOneSubscriberToUpdate() throws Exception { expect(schemaFactory.open()).andReturn(schema); - final Repository sourceRepository = createWorkRepository(); - final Git sourceGit = new Git(sourceRepository); + try (Repository sourceRepository = createWorkRepository(); + Repository targetRepository = createWorkRepository()) { + // TODO(dborowitz): Use try/finally when this doesn't double-close the repo. + @SuppressWarnings("resource") + final Git sourceGit = new Git(sourceRepository); + // TODO(dborowitz): Use try/finally when this doesn't double-close the repo. + @SuppressWarnings("resource") + final Git targetGit = new Git(targetRepository); - addRegularFileToIndex("file.txt", "test content", sourceRepository); + addRegularFileToIndex("file.txt", "test content", sourceRepository); - final RevCommit sourceMergeTip = - sourceGit.commit().setMessage("test").call(); + final RevCommit sourceMergeTip = + sourceGit.commit().setMessage("test").call(); - final Branch.NameKey sourceBranchNameKey = - new Branch.NameKey(new Project.NameKey("source-project"), - "refs/heads/master"); + final Branch.NameKey sourceBranchNameKey = + new Branch.NameKey(new Project.NameKey("source-project"), + "refs/heads/master"); - final CodeReviewCommit codeReviewCommit = - new CodeReviewCommit(sourceMergeTip.toObjectId()); - final Change submittedChange = new Change( - new Change.Key(sourceMergeTip.toObjectId().getName()), new Change.Id(1), - new Account.Id(1), sourceBranchNameKey, TimeUtil.nowTs()); + final CodeReviewCommit codeReviewCommit = + new CodeReviewCommit(sourceMergeTip.toObjectId()); + final Change submittedChange = new Change( + new Change.Key(sourceMergeTip.toObjectId().getName()), new Change.Id(1), + new Account.Id(1), sourceBranchNameKey, TimeUtil.nowTs()); - final Map<Change.Id, CodeReviewCommit> mergedCommits = new HashMap<>(); - mergedCommits.put(submittedChange.getId(), codeReviewCommit); + final Map<Change.Id, CodeReviewCommit> mergedCommits = new HashMap<>(); + mergedCommits.put(submittedChange.getId(), codeReviewCommit); - final List<Change> submitted = new ArrayList<>(); - submitted.add(submittedChange); + final List<Change> submitted = new ArrayList<>(); + submitted.add(submittedChange); - final Repository targetRepository = createWorkRepository(); - final Git targetGit = new Git(targetRepository); + addGitLinkToIndex("a", sourceMergeTip.copy(), targetRepository); - addGitLinkToIndex("a", sourceMergeTip.copy(), targetRepository); + targetGit.commit().setMessage("test").call(); - targetGit.commit().setMessage("test").call(); + final Branch.NameKey targetBranchNameKey = + new Branch.NameKey(new Project.NameKey("target-project"), + sourceBranchNameKey.get()); - final Branch.NameKey targetBranchNameKey = - new Branch.NameKey(new Project.NameKey("target-project"), - sourceBranchNameKey.get()); + expect(urlProvider.get()).andReturn("http://localhost:8080"); - expect(urlProvider.get()).andReturn("http://localhost:8080"); + expect(schema.submoduleSubscriptions()).andReturn(subscriptions); + final ResultSet<SubmoduleSubscription> subscribers = + new ListResultSet<>(Collections + .singletonList(new SubmoduleSubscription(targetBranchNameKey, + sourceBranchNameKey, "source-project"))); + expect(subscriptions.bySubmodule(sourceBranchNameKey)).andReturn( + subscribers); - expect(schema.submoduleSubscriptions()).andReturn(subscriptions); - final ResultSet<SubmoduleSubscription> subscribers = - new ListResultSet<>(Collections - .singletonList(new SubmoduleSubscription(targetBranchNameKey, - sourceBranchNameKey, "source-project"))); - expect(subscriptions.bySubmodule(sourceBranchNameKey)).andReturn( - subscribers); + expect(repoManager.openRepository(targetBranchNameKey.getParentKey())) + .andReturn(targetRepository).anyTimes(); - expect(repoManager.openRepository(targetBranchNameKey.getParentKey())) - .andReturn(targetRepository).anyTimes(); + Capture<RefUpdate> ruCapture = new Capture<>(); + gitRefUpdated.fire(eq(targetBranchNameKey.getParentKey()), + capture(ruCapture)); + changeHooks.doRefUpdatedHook(eq(targetBranchNameKey), + anyObject(RefUpdate.class), EasyMock.<Account>isNull()); - Capture<RefUpdate> ruCapture = new Capture<>(); - gitRefUpdated.fire(eq(targetBranchNameKey.getParentKey()), - capture(ruCapture)); - changeHooks.doRefUpdatedHook(eq(targetBranchNameKey), - anyObject(RefUpdate.class), EasyMock.<Account>isNull()); + expect(schema.submoduleSubscriptions()).andReturn(subscriptions); + final ResultSet<SubmoduleSubscription> emptySubscriptions = + new ListResultSet<>(new ArrayList<SubmoduleSubscription>()); + expect(subscriptions.bySubmodule(targetBranchNameKey)).andReturn( + emptySubscriptions); - expect(schema.submoduleSubscriptions()).andReturn(subscriptions); - final ResultSet<SubmoduleSubscription> emptySubscriptions = - new ListResultSet<>(new ArrayList<SubmoduleSubscription>()); - expect(subscriptions.bySubmodule(targetBranchNameKey)).andReturn( - emptySubscriptions); + schema.close(); - schema.close(); + final PersonIdent myIdent = + new PersonIdent("test-user", "test-user@email.com"); - final PersonIdent myIdent = - new PersonIdent("test-user", "test-user@email.com"); + doReplay(); - doReplay(); + final SubmoduleOp submoduleOp = + new SubmoduleOp(sourceBranchNameKey, sourceMergeTip, new RevWalk( + sourceRepository), urlProvider, schemaFactory, sourceRepository, + new Project(sourceBranchNameKey.getParentKey()), submitted, + mergedCommits, myIdent, repoManager, gitRefUpdated, null, + changeHooks); - final SubmoduleOp submoduleOp = - new SubmoduleOp(sourceBranchNameKey, sourceMergeTip, new RevWalk( - sourceRepository), urlProvider, schemaFactory, sourceRepository, - new Project(sourceBranchNameKey.getParentKey()), submitted, - mergedCommits, myIdent, repoManager, gitRefUpdated, null, - changeHooks); + submoduleOp.update(); - submoduleOp.update(); - - doVerify(); - RefUpdate ru = ruCapture.getValue(); - assertEquals(ru.getName(), targetBranchNameKey.get()); + doVerify(); + RefUpdate ru = ruCapture.getValue(); + assertEquals(ru.getName(), targetBranchNameKey.get()); + } } /** @@ -693,86 +700,90 @@ public void testAvoidingCircularReference() throws Exception { expect(schemaFactory.open()).andReturn(schema); - final Repository sourceRepository = createWorkRepository(); - final Git sourceGit = new Git(sourceRepository); + try (Repository sourceRepository = createWorkRepository(); + Repository targetRepository = createWorkRepository()) { + // TODO(dborowitz): Use try/finally when this doesn't double-close the repo. + @SuppressWarnings("resource") + final Git sourceGit = new Git(sourceRepository); + // TODO(dborowitz): Use try/finally when this doesn't double-close the repo. + @SuppressWarnings("resource") + final Git targetGit = new Git(targetRepository); - addRegularFileToIndex("file.txt", "test content", sourceRepository); + addRegularFileToIndex("file.txt", "test content", sourceRepository); - final RevCommit sourceMergeTip = - sourceGit.commit().setMessage("test").call(); + final RevCommit sourceMergeTip = + sourceGit.commit().setMessage("test").call(); - final Branch.NameKey sourceBranchNameKey = - new Branch.NameKey(new Project.NameKey("source-project"), - "refs/heads/master"); + final Branch.NameKey sourceBranchNameKey = + new Branch.NameKey(new Project.NameKey("source-project"), + "refs/heads/master"); - final CodeReviewCommit codeReviewCommit = - new CodeReviewCommit(sourceMergeTip.toObjectId()); - final Change submittedChange = new Change( - new Change.Key(sourceMergeTip.toObjectId().getName()), new Change.Id(1), - new Account.Id(1), sourceBranchNameKey, TimeUtil.nowTs()); + final CodeReviewCommit codeReviewCommit = + new CodeReviewCommit(sourceMergeTip.toObjectId()); + final Change submittedChange = new Change( + new Change.Key(sourceMergeTip.toObjectId().getName()), new Change.Id(1), + new Account.Id(1), sourceBranchNameKey, TimeUtil.nowTs()); - final Map<Change.Id, CodeReviewCommit> mergedCommits = new HashMap<>(); - mergedCommits.put(submittedChange.getId(), codeReviewCommit); + final Map<Change.Id, CodeReviewCommit> mergedCommits = new HashMap<>(); + mergedCommits.put(submittedChange.getId(), codeReviewCommit); - final List<Change> submitted = new ArrayList<>(); - submitted.add(submittedChange); + final List<Change> submitted = new ArrayList<>(); + submitted.add(submittedChange); - final Repository targetRepository = createWorkRepository(); - final Git targetGit = new Git(targetRepository); + addGitLinkToIndex("a", sourceMergeTip.copy(), targetRepository); - addGitLinkToIndex("a", sourceMergeTip.copy(), targetRepository); + targetGit.commit().setMessage("test").call(); - targetGit.commit().setMessage("test").call(); + final Branch.NameKey targetBranchNameKey = + new Branch.NameKey(new Project.NameKey("target-project"), + sourceBranchNameKey.get()); - final Branch.NameKey targetBranchNameKey = - new Branch.NameKey(new Project.NameKey("target-project"), - sourceBranchNameKey.get()); + expect(urlProvider.get()).andReturn("http://localhost:8080"); - expect(urlProvider.get()).andReturn("http://localhost:8080"); + expect(schema.submoduleSubscriptions()).andReturn(subscriptions); + final ResultSet<SubmoduleSubscription> subscribers = + new ListResultSet<>(Collections + .singletonList(new SubmoduleSubscription(targetBranchNameKey, + sourceBranchNameKey, "source-project"))); + expect(subscriptions.bySubmodule(sourceBranchNameKey)).andReturn( + subscribers); - expect(schema.submoduleSubscriptions()).andReturn(subscriptions); - final ResultSet<SubmoduleSubscription> subscribers = - new ListResultSet<>(Collections - .singletonList(new SubmoduleSubscription(targetBranchNameKey, - sourceBranchNameKey, "source-project"))); - expect(subscriptions.bySubmodule(sourceBranchNameKey)).andReturn( - subscribers); + expect(repoManager.openRepository(targetBranchNameKey.getParentKey())) + .andReturn(targetRepository).anyTimes(); - expect(repoManager.openRepository(targetBranchNameKey.getParentKey())) - .andReturn(targetRepository).anyTimes(); + Capture<RefUpdate> ruCapture = new Capture<>(); + gitRefUpdated.fire(eq(targetBranchNameKey.getParentKey()), + capture(ruCapture)); + changeHooks.doRefUpdatedHook(eq(targetBranchNameKey), + anyObject(RefUpdate.class), EasyMock.<Account>isNull()); - Capture<RefUpdate> ruCapture = new Capture<>(); - gitRefUpdated.fire(eq(targetBranchNameKey.getParentKey()), - capture(ruCapture)); - changeHooks.doRefUpdatedHook(eq(targetBranchNameKey), - anyObject(RefUpdate.class), EasyMock.<Account>isNull()); + expect(schema.submoduleSubscriptions()).andReturn(subscriptions); + final ResultSet<SubmoduleSubscription> incorrectSubscriptions = + new ListResultSet<>(Collections + .singletonList(new SubmoduleSubscription(sourceBranchNameKey, + targetBranchNameKey, "target-project"))); + expect(subscriptions.bySubmodule(targetBranchNameKey)).andReturn( + incorrectSubscriptions); - expect(schema.submoduleSubscriptions()).andReturn(subscriptions); - final ResultSet<SubmoduleSubscription> incorrectSubscriptions = - new ListResultSet<>(Collections - .singletonList(new SubmoduleSubscription(sourceBranchNameKey, - targetBranchNameKey, "target-project"))); - expect(subscriptions.bySubmodule(targetBranchNameKey)).andReturn( - incorrectSubscriptions); + schema.close(); - schema.close(); + final PersonIdent myIdent = + new PersonIdent("test-user", "test-user@email.com"); - final PersonIdent myIdent = - new PersonIdent("test-user", "test-user@email.com"); + doReplay(); - doReplay(); + final SubmoduleOp submoduleOp = + new SubmoduleOp(sourceBranchNameKey, sourceMergeTip, new RevWalk( + sourceRepository), urlProvider, schemaFactory, sourceRepository, + new Project(sourceBranchNameKey.getParentKey()), submitted, + mergedCommits, myIdent, repoManager, gitRefUpdated, null, changeHooks); - final SubmoduleOp submoduleOp = - new SubmoduleOp(sourceBranchNameKey, sourceMergeTip, new RevWalk( - sourceRepository), urlProvider, schemaFactory, sourceRepository, - new Project(sourceBranchNameKey.getParentKey()), submitted, - mergedCommits, myIdent, repoManager, gitRefUpdated, null, changeHooks); + submoduleOp.update(); - submoduleOp.update(); - - doVerify(); - RefUpdate ru = ruCapture.getValue(); - assertEquals(ru.getName(), targetBranchNameKey.get()); + doVerify(); + RefUpdate ru = ruCapture.getValue(); + assertEquals(ru.getName(), targetBranchNameKey.get()); + } } /** @@ -862,67 +873,70 @@ final List<SubmoduleSubscription> previousSubscriptions) throws Exception { expect(schemaFactory.open()).andReturn(schema); - final Repository realDb = createWorkRepository(); - final Git git = new Git(realDb); + try (Repository realDb = createWorkRepository()) { + // TODO(dborowitz): Use try/finally when this doesn't double-close the repo. + @SuppressWarnings("resource") + final Git git = new Git(realDb); - addRegularFileToIndex(".gitmodules", gitModulesFileContent, realDb); + addRegularFileToIndex(".gitmodules", gitModulesFileContent, realDb); - final RevCommit mergeTip = git.commit().setMessage("test").call(); + final RevCommit mergeTip = git.commit().setMessage("test").call(); - expect(urlProvider.get()).andReturn("http://localhost:8080").times(2); + expect(urlProvider.get()).andReturn("http://localhost:8080").times(2); - expect(schema.submoduleSubscriptions()).andReturn(subscriptions); - expect(subscriptions.bySuperProject(mergedBranch)).andReturn( - new ListResultSet<>(previousSubscriptions)); - - SortedSet<Project.NameKey> existingProjects = new TreeSet<>(); - - for (SubmoduleSubscription extracted : extractedSubscriptions) { - existingProjects.add(extracted.getSubmodule().getParentKey()); - } - - for (int index = 0; index < extractedSubscriptions.size(); index++) { - expect(repoManager.list()).andReturn(existingProjects); - } - - final Set<SubmoduleSubscription> alreadySubscribeds = new HashSet<>(); - for (SubmoduleSubscription s : extractedSubscriptions) { - if (previousSubscriptions.contains(s)) { - alreadySubscribeds.add(s); - } - } - - final Set<SubmoduleSubscription> subscriptionsToRemove = - new HashSet<>(previousSubscriptions); - final List<SubmoduleSubscription> subscriptionsToInsert = - new ArrayList<>(extractedSubscriptions); - - subscriptionsToRemove.removeAll(subscriptionsToInsert); - subscriptionsToInsert.removeAll(alreadySubscribeds); - - if (!subscriptionsToRemove.isEmpty()) { expect(schema.submoduleSubscriptions()).andReturn(subscriptions); - subscriptions.delete(subscriptionsToRemove); + expect(subscriptions.bySuperProject(mergedBranch)).andReturn( + new ListResultSet<>(previousSubscriptions)); + + SortedSet<Project.NameKey> existingProjects = new TreeSet<>(); + + for (SubmoduleSubscription extracted : extractedSubscriptions) { + existingProjects.add(extracted.getSubmodule().getParentKey()); + } + + for (int index = 0; index < extractedSubscriptions.size(); index++) { + expect(repoManager.list()).andReturn(existingProjects); + } + + final Set<SubmoduleSubscription> alreadySubscribeds = new HashSet<>(); + for (SubmoduleSubscription s : extractedSubscriptions) { + if (previousSubscriptions.contains(s)) { + alreadySubscribeds.add(s); + } + } + + final Set<SubmoduleSubscription> subscriptionsToRemove = + new HashSet<>(previousSubscriptions); + final List<SubmoduleSubscription> subscriptionsToInsert = + new ArrayList<>(extractedSubscriptions); + + subscriptionsToRemove.removeAll(subscriptionsToInsert); + subscriptionsToInsert.removeAll(alreadySubscribeds); + + if (!subscriptionsToRemove.isEmpty()) { + expect(schema.submoduleSubscriptions()).andReturn(subscriptions); + subscriptions.delete(subscriptionsToRemove); + } + + expect(schema.submoduleSubscriptions()).andReturn(subscriptions); + subscriptions.insert(subscriptionsToInsert); + + expect(schema.submoduleSubscriptions()).andReturn(subscriptions); + expect(subscriptions.bySubmodule(mergedBranch)).andReturn( + new ListResultSet<>(new ArrayList<SubmoduleSubscription>())); + + schema.close(); + + doReplay(); + + final SubmoduleOp submoduleOp = + new SubmoduleOp(mergedBranch, mergeTip, new RevWalk(realDb), + urlProvider, schemaFactory, realDb, new Project(mergedBranch + .getParentKey()), new ArrayList<Change>(), null, null, + repoManager, null, null, null); + + submoduleOp.update(); } - - expect(schema.submoduleSubscriptions()).andReturn(subscriptions); - subscriptions.insert(subscriptionsToInsert); - - expect(schema.submoduleSubscriptions()).andReturn(subscriptions); - expect(subscriptions.bySubmodule(mergedBranch)).andReturn( - new ListResultSet<>(new ArrayList<SubmoduleSubscription>())); - - schema.close(); - - doReplay(); - - final SubmoduleOp submoduleOp = - new SubmoduleOp(mergedBranch, mergeTip, new RevWalk(realDb), - urlProvider, schemaFactory, realDb, new Project(mergedBranch - .getParentKey()), new ArrayList<Change>(), null, null, - repoManager, null, null, null); - - submoduleOp.update(); } /**
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesParserTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesParserTest.java index 53d9fb1..c41c4ec 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesParserTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesParserTest.java
@@ -43,7 +43,7 @@ @After public void tearDownTestRepo() throws Exception { - walk.release(); + walk.close(); } @Test @@ -176,8 +176,7 @@ private RevCommit writeCommit(String body, PersonIdent author) throws Exception { - ObjectInserter ins = testRepo.getRepository().newObjectInserter(); - try { + try (ObjectInserter ins = testRepo.getRepository().newObjectInserter()) { CommitBuilder cb = new CommitBuilder(); cb.setAuthor(author); cb.setCommitter(new PersonIdent(serverIdent, author.getWhen())); @@ -188,8 +187,6 @@ RevCommit commit = walk.parseCommit(id); walk.parseBody(commit); return commit; - } finally { - ins.release(); } }
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java index db17f80..aea966a 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java
@@ -348,13 +348,10 @@ hashtags.add("tag2"); update.setHashtags(hashtags); update.commit(); - RevWalk walk = new RevWalk(repo); - try { + try (RevWalk walk = new RevWalk(repo)) { RevCommit commit = walk.parseCommit(update.getRevision()); walk.parseBody(commit); assertTrue(commit.getFullMessage().endsWith("Hashtags: tag1,tag2\n")); - } finally { - walk.release(); } } @@ -433,8 +430,7 @@ update2.putApproval("Code-Review", (short) 2); update2.writeCommit(batch); - RevWalk rw = new RevWalk(repo); - try { + try (RevWalk rw = new RevWalk(repo)) { batch.commit(); bru.execute(rw, NullProgressMonitor.INSTANCE); @@ -464,7 +460,6 @@ notesWithApprovals.close(); } finally { batch.close(); - rw.release(); } } @@ -506,11 +501,8 @@ assertEquals(update1.getRefName(), cmds.get(0).getRefName()); assertEquals(update2.getRefName(), cmds.get(1).getRefName()); - RevWalk rw = new RevWalk(repo); - try { + try (RevWalk rw = new RevWalk(repo)) { bru.execute(rw, NullProgressMonitor.INSTANCE); - } finally { - rw.release(); } assertEquals(ReceiveCommand.Result.OK, cmds.get(0).getResult()); @@ -712,43 +704,44 @@ ChangeNotes notes = newNotes(c); - RevWalk walk = new RevWalk(repo); - ArrayList<Note> notesInTree = - Lists.newArrayList(notes.getNoteMap().iterator()); - Note note = Iterables.getOnlyElement(notesInTree); + try (RevWalk walk = new RevWalk(repo)) { + ArrayList<Note> notesInTree = + Lists.newArrayList(notes.getNoteMap().iterator()); + Note note = Iterables.getOnlyElement(notesInTree); - byte[] bytes = - walk.getObjectReader().open( - note.getData(), Constants.OBJ_BLOB).getBytes(); - String noteString = new String(bytes, UTF_8); - assertEquals("Patch-set: 1\n" - + "Revision: abcd1234abcd1234abcd1234abcd1234abcd1234\n" - + "File: file1\n" - + "\n" - + "1:1-2:1\n" - + CommentsInNotesUtil.formatTime(serverIdent, time1) + "\n" - + "Author: Other Account <2@gerrit>\n" - + "UUID: uuid1\n" - + "Bytes: 9\n" - + "comment 1\n" - + "\n" - + "2:1-3:1\n" - + CommentsInNotesUtil.formatTime(serverIdent, time2) + "\n" - + "Author: Other Account <2@gerrit>\n" - + "UUID: uuid2\n" - + "Bytes: 9\n" - + "comment 2\n" - + "\n" - + "File: file2\n" - + "\n" - + "3:1-4:1\n" - + CommentsInNotesUtil.formatTime(serverIdent, time3) + "\n" - + "Author: Other Account <2@gerrit>\n" - + "UUID: uuid3\n" - + "Bytes: 9\n" - + "comment 3\n" - + "\n", - noteString); + byte[] bytes = + walk.getObjectReader().open( + note.getData(), Constants.OBJ_BLOB).getBytes(); + String noteString = new String(bytes, UTF_8); + assertEquals("Patch-set: 1\n" + + "Revision: abcd1234abcd1234abcd1234abcd1234abcd1234\n" + + "File: file1\n" + + "\n" + + "1:1-2:1\n" + + CommentsInNotesUtil.formatTime(serverIdent, time1) + "\n" + + "Author: Other Account <2@gerrit>\n" + + "UUID: uuid1\n" + + "Bytes: 9\n" + + "comment 1\n" + + "\n" + + "2:1-3:1\n" + + CommentsInNotesUtil.formatTime(serverIdent, time2) + "\n" + + "Author: Other Account <2@gerrit>\n" + + "UUID: uuid2\n" + + "Bytes: 9\n" + + "comment 2\n" + + "\n" + + "File: file2\n" + + "\n" + + "3:1-4:1\n" + + CommentsInNotesUtil.formatTime(serverIdent, time3) + "\n" + + "Author: Other Account <2@gerrit>\n" + + "UUID: uuid3\n" + + "Bytes: 9\n" + + "comment 3\n" + + "\n", + noteString); + } } @Test @@ -782,34 +775,35 @@ ChangeNotes notes = newNotes(c); - RevWalk walk = new RevWalk(repo); - ArrayList<Note> notesInTree = - Lists.newArrayList(notes.getNoteMap().iterator()); - Note note = Iterables.getOnlyElement(notesInTree); + try (RevWalk walk = new RevWalk(repo)) { + ArrayList<Note> notesInTree = + Lists.newArrayList(notes.getNoteMap().iterator()); + Note note = Iterables.getOnlyElement(notesInTree); - byte[] bytes = - walk.getObjectReader().open( - note.getData(), Constants.OBJ_BLOB).getBytes(); - String noteString = new String(bytes, UTF_8); - assertEquals("Base-for-patch-set: 1\n" - + "Revision: abcd1234abcd1234abcd1234abcd1234abcd1234\n" - + "File: file1\n" - + "\n" - + "1:1-2:1\n" - + CommentsInNotesUtil.formatTime(serverIdent, time1) + "\n" - + "Author: Other Account <2@gerrit>\n" - + "UUID: uuid1\n" - + "Bytes: 9\n" - + "comment 1\n" - + "\n" - + "2:1-3:1\n" - + CommentsInNotesUtil.formatTime(serverIdent, time2) + "\n" - + "Author: Other Account <2@gerrit>\n" - + "UUID: uuid2\n" - + "Bytes: 9\n" - + "comment 2\n" - + "\n", - noteString); + byte[] bytes = + walk.getObjectReader().open( + note.getData(), Constants.OBJ_BLOB).getBytes(); + String noteString = new String(bytes, UTF_8); + assertEquals("Base-for-patch-set: 1\n" + + "Revision: abcd1234abcd1234abcd1234abcd1234abcd1234\n" + + "File: file1\n" + + "\n" + + "1:1-2:1\n" + + CommentsInNotesUtil.formatTime(serverIdent, time1) + "\n" + + "Author: Other Account <2@gerrit>\n" + + "UUID: uuid1\n" + + "Bytes: 9\n" + + "comment 1\n" + + "\n" + + "2:1-3:1\n" + + CommentsInNotesUtil.formatTime(serverIdent, time2) + "\n" + + "Author: Other Account <2@gerrit>\n" + + "UUID: uuid2\n" + + "Bytes: 9\n" + + "comment 2\n" + + "\n", + noteString); + } } @Test
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/CommitMessageOutputTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/CommitMessageOutputTest.java index 86f9702..328509a 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/CommitMessageOutputTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
@@ -242,13 +242,10 @@ if (id instanceof RevCommit) { return (RevCommit) id; } - RevWalk walk = new RevWalk(repo); - try { + try (RevWalk walk = new RevWalk(repo)) { RevCommit commit = walk.parseCommit(id); walk.parseBody(commit); return commit; - } finally { - walk.release(); } }
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java index 8686fe6..806dca6 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java
@@ -43,9 +43,10 @@ import org.junit.Before; import org.junit.Test; -import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import java.util.UUID; @@ -67,7 +68,7 @@ IOException { db.create(); - final File site = new File(UUID.randomUUID().toString()); + final Path site = Paths.get(UUID.randomUUID().toString()); final SitePaths paths = new SitePaths(site); SchemaUpdater u = Guice.createInjector(new FactoryModule() { @Override @@ -129,6 +130,6 @@ db.assertSchemaVersion(); final SystemConfig sc = db.getSystemConfig(); - assertEquals(paths.site_path.getCanonicalPath(), sc.sitePath); + assertEquals(paths.site_path.toAbsolutePath().toString(), sc.sitePath); } }
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/tools/hooks/CommitMsgHookTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/tools/hooks/CommitMsgHookTest.java index 17fe068..9c8e86a 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/tools/hooks/CommitMsgHookTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/tools/hooks/CommitMsgHookTest.java
@@ -423,21 +423,17 @@ } private DirCacheEntry file(final String name) throws IOException { - final ObjectInserter oi = repository.newObjectInserter(); - try { + try (ObjectInserter oi = repository.newObjectInserter()) { final DirCacheEntry e = new DirCacheEntry(name); e.setFileMode(FileMode.REGULAR_FILE); e.setObjectId(oi.insert(Constants.OBJ_BLOB, Constants.encode(name))); oi.flush(); return e; - } finally { - oi.release(); } } private void setHEAD() throws Exception { - final ObjectInserter oi = repository.newObjectInserter(); - try { + try (ObjectInserter oi = repository.newObjectInserter()) { final CommitBuilder commit = new CommitBuilder(); commit.setTreeId(oi.insert(Constants.OBJ_TREE, new byte[] {})); commit.setAuthor(author); @@ -456,8 +452,6 @@ default: fail(Constants.HEAD + " did not change: " + ref.getResult()); } - } finally { - oi.release(); } } }
diff --git a/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java b/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java index 72495b3..f33cfb2 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java +++ b/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryModule.java
@@ -69,11 +69,12 @@ import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.PersonIdent; -import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.nio.file.Path; +import java.nio.file.Paths; public class InMemoryModule extends FactoryModule { public static Config newDefaultConfig() { @@ -125,7 +126,8 @@ bindScope(RequestScoped.class, PerThreadRequestScope.REQUEST); - bind(File.class).annotatedWith(SitePath.class).toInstance(new File(".")); + // TODO(dborowitz): Use jimfs. + bind(Path.class).annotatedWith(SitePath.class).toInstance(Paths.get(".")); bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(cfg); bind(SocketAddress.class).annotatedWith(RemotePeer.class).toInstance( new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 1234));
diff --git a/gerrit-solr/src/main/java/com/google/gerrit/solr/IndexVersionCheck.java b/gerrit-solr/src/main/java/com/google/gerrit/solr/IndexVersionCheck.java index ddb86c3..0faa691 100644 --- a/gerrit-solr/src/main/java/com/google/gerrit/solr/IndexVersionCheck.java +++ b/gerrit-solr/src/main/java/com/google/gerrit/solr/IndexVersionCheck.java
@@ -25,8 +25,8 @@ import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.Map; class IndexVersionCheck implements LifecycleListener { @@ -34,8 +34,8 @@ SolrChangeIndex.CHANGES_OPEN, ChangeSchemas.getLatest().getVersion(), SolrChangeIndex.CHANGES_CLOSED, ChangeSchemas.getLatest().getVersion()); - public static File solrIndexConfig(SitePaths sitePaths) { - return new File(sitePaths.index_dir, "gerrit_index.config"); + public static Path solrIndexConfig(SitePaths sitePaths) { + return sitePaths.index_dir.resolve("gerrit_index.config"); } private final SitePaths sitePaths; @@ -48,9 +48,9 @@ @Override public void start() { // TODO Query schema version from a special meta-document - File file = solrIndexConfig(sitePaths); + Path path = solrIndexConfig(sitePaths); try { - FileBasedConfig cfg = new FileBasedConfig(file, FS.detect()); + FileBasedConfig cfg = new FileBasedConfig(path.toFile(), FS.detect()); cfg.load(); for (Map.Entry<String, Integer> e : SCHEMA_VERSIONS.entrySet()) { int schemaVersion = cfg.getInt("index", e.getKey(), "schemaVersion", 0); @@ -61,9 +61,9 @@ } } } catch (IOException e) { - throw new ProvisionException("unable to read " + file); + throw new ProvisionException("unable to read " + path); } catch (ConfigInvalidException e) { - throw new ProvisionException("invalid config file " + file); + throw new ProvisionException("invalid config file " + path); } } @@ -75,6 +75,6 @@ private final String upgrade() { return "\nRun reindex to rebuild the index:\n" + "$ java -jar gerrit.war reindex -d " - + sitePaths.site_path.getAbsolutePath(); + + sitePaths.site_path.toAbsolutePath(); } }
diff --git a/gerrit-solr/src/main/java/com/google/gerrit/solr/SolrChangeIndex.java b/gerrit-solr/src/main/java/com/google/gerrit/solr/SolrChangeIndex.java index 78f5265..ab95ae4 100644 --- a/gerrit-solr/src/main/java/com/google/gerrit/solr/SolrChangeIndex.java +++ b/gerrit-solr/src/main/java/com/google/gerrit/solr/SolrChangeIndex.java
@@ -327,7 +327,7 @@ public void markReady(boolean ready) throws IOException { // TODO Move the schema version information to a special meta-document FileBasedConfig cfg = new FileBasedConfig( - solrIndexConfig(sitePaths), + solrIndexConfig(sitePaths).toFile(), FS.detect()); for (Map.Entry<String, Integer> e : SCHEMA_VERSIONS.entrySet()) { cfg.setInt("index", e.getKey(), "schemaVersion",
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java index 93d2e5b..ab3b446 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java
@@ -14,6 +14,9 @@ package com.google.gerrit.sshd; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.gerrit.common.FileUtil; import com.google.gerrit.reviewdb.client.AccountSshKey; import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.PeerDaemonUser; @@ -33,10 +36,10 @@ import org.slf4j.LoggerFactory; import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; import java.security.KeyPair; import java.security.PublicKey; import java.util.Collection; @@ -170,56 +173,50 @@ } private static class PeerKeyCache { - private final File path; + private final Path path; private final long modified; final Set<PublicKey> keys; - PeerKeyCache(final File path) { + PeerKeyCache(Path path) { this.path = path; - this.modified = path.lastModified(); + this.modified = FileUtil.lastModified(path); this.keys = read(path); } - private static Set<PublicKey> read(File path) { - try { - final BufferedReader br = new BufferedReader(new FileReader(path)); - try { - final Set<PublicKey> keys = new HashSet<>(); - String line; - while ((line = br.readLine()) != null) { - line = line.trim(); - if (line.startsWith("#") || line.isEmpty()) { - continue; - } - - try { - byte[] bin = Base64.decodeBase64(line.getBytes("ISO-8859-1")); - keys.add(new Buffer(bin).getRawPublicKey()); - } catch (RuntimeException e) { - logBadKey(path, line, e); - } catch (SshException e) { - logBadKey(path, line, e); - } + private static Set<PublicKey> read(Path path) { + try (BufferedReader br = Files.newBufferedReader(path, UTF_8)) { + final Set<PublicKey> keys = new HashSet<>(); + String line; + while ((line = br.readLine()) != null) { + line = line.trim(); + if (line.startsWith("#") || line.isEmpty()) { + continue; } - return Collections.unmodifiableSet(keys); - } finally { - br.close(); - } - } catch (FileNotFoundException noFile) { - return Collections.emptySet(); + try { + byte[] bin = Base64.decodeBase64(line.getBytes("ISO-8859-1")); + keys.add(new Buffer(bin).getRawPublicKey()); + } catch (RuntimeException e) { + logBadKey(path, line, e); + } catch (SshException e) { + logBadKey(path, line, e); + } + } + return Collections.unmodifiableSet(keys); + } catch (NoSuchFileException noFile) { + return Collections.emptySet(); } catch (IOException err) { log.error("Cannot read " + path, err); return Collections.emptySet(); } } - private static void logBadKey(File path, String line, Exception e) { + private static void logBadKey(Path path, String line, Exception e) { log.warn("Invalid key in " + path + ":\n " + line, e); } boolean isCurrent() { - return path.lastModified() == modified; + return modified == FileUtil.lastModified(path); } PeerKeyCache reload() {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java index 241f853..3e6e2f5 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/HostKeyProvider.java
@@ -24,7 +24,8 @@ import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; -import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -38,29 +39,29 @@ @Override public KeyPairProvider get() { - final File objKey = site.ssh_key; - final File rsaKey = site.ssh_rsa; - final File dsaKey = site.ssh_dsa; + Path objKey = site.ssh_key; + Path rsaKey = site.ssh_rsa; + Path dsaKey = site.ssh_dsa; final List<String> stdKeys = new ArrayList<>(2); - if (rsaKey.exists()) { - stdKeys.add(rsaKey.getAbsolutePath()); + if (Files.exists(rsaKey)) { + stdKeys.add(rsaKey.toAbsolutePath().toString()); } - if (dsaKey.exists()) { - stdKeys.add(dsaKey.getAbsolutePath()); + if (Files.exists(dsaKey)) { + stdKeys.add(dsaKey.toAbsolutePath().toString()); } - if (objKey.exists()) { + if (Files.exists(objKey)) { if (stdKeys.isEmpty()) { SimpleGeneratorHostKeyProvider p = new SimpleGeneratorHostKeyProvider(); - p.setPath(objKey.getAbsolutePath()); + p.setPath(objKey.toAbsolutePath().toString()); return p; } else { // Both formats of host key exist, we don't know which format // should be authoritative. Complain and abort. // - stdKeys.add(objKey.getAbsolutePath()); + stdKeys.add(objKey.toAbsolutePath().toString()); throw new ProvisionException("Multiple host keys exist: " + stdKeys); }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java index f75eb2b..e4b21d1 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
@@ -73,12 +73,18 @@ command("suexec").to(SuExec.class); listener().to(ShowCaches.StartupListener.class); - // The following commands can only be ran on a server in Master mode + // The following commands can only be run on a server in Master mode command(gerrit, CreateAccountCommand.class); command(gerrit, CreateGroupCommand.class); command(gerrit, CreateProjectCommand.class); + command(gerrit, SetHeadCommand.class); command(gerrit, AdminQueryShell.class); - if (!slaveMode) { + if (slaveMode) { + command("git-receive-pack").to(NotSupportedInSlaveModeFailureCommand.class); + command("gerrit-receive-pack").to(NotSupportedInSlaveModeFailureCommand.class); + command(git, "receive-pack").to(NotSupportedInSlaveModeFailureCommand.class); + command(gerrit, "test-submit").to(NotSupportedInSlaveModeFailureCommand.class); + } else { command("git-receive-pack").to(Commands.key(git, "receive-pack")); command("gerrit-receive-pack").to(Commands.key(git, "receive-pack")); command(git, "receive-pack").to(Commands.key(gerrit, "receive-pack"));
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/NotSupportedInSlaveModeFailureCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/NotSupportedInSlaveModeFailureCommand.java new file mode 100644 index 0000000..39e6d4a --- /dev/null +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/NotSupportedInSlaveModeFailureCommand.java
@@ -0,0 +1,25 @@ +// Copyright (C) 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.sshd.commands; + +import com.google.gerrit.sshd.SshCommand; + +/* Failure command, that produces verbose failure message in slave mode */ +public class NotSupportedInSlaveModeFailureCommand extends SshCommand { + @Override + protected void run() throws UnloggedFailure { + throw die(getName() + ": is not supported in slave mode"); + } +}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetHeadCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetHeadCommand.java new file mode 100644 index 0000000..b1d1605 --- /dev/null +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetHeadCommand.java
@@ -0,0 +1,55 @@ +// Copyright (C) 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.sshd.commands; + +import com.google.gerrit.extensions.restapi.UnprocessableEntityException; +import com.google.gerrit.server.project.ProjectControl; +import com.google.gerrit.server.project.ProjectResource; +import com.google.gerrit.server.project.SetHead; +import com.google.gerrit.server.project.SetHead.Input; +import com.google.gerrit.sshd.CommandMetaData; +import com.google.gerrit.sshd.SshCommand; +import com.google.inject.Inject; + +import org.kohsuke.args4j.Argument; +import org.kohsuke.args4j.Option; + +@CommandMetaData(name = "set-head", description = "Change HEAD reference for a project") +public class SetHeadCommand extends SshCommand { + + @Argument(index = 0, required = true, metaVar = "NAME", usage = "name of the project") + private ProjectControl project; + + @Option(name = "--new-head", required = true, metaVar = "REF", usage = "new HEAD reference") + private String newHead; + + private final SetHead setHead; + + @Inject + SetHeadCommand(SetHead setHead) { + this.setHead = setHead; + } + + @Override + protected void run() throws Exception { + Input input = new SetHead.Input(); + input.ref = newHead; + try { + setHead.apply(new ProjectResource(project), input); + } catch (UnprocessableEntityException e) { + throw new UnloggedFailure("fatal: " + e.getMessage()); + } + } +}
diff --git a/gerrit-war/pom.xml b/gerrit-war/pom.xml index 81d8498..17e8286 100644 --- a/gerrit-war/pom.xml +++ b/gerrit-war/pom.xml
@@ -2,7 +2,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-war</artifactId> - <version>2.11-SNAPSHOT</version> + <version>2.12-SNAPSHOT</version> <packaging>war</packaging> <name>Gerrit Code Review - WAR</name> <description>Gerrit WAR</description>
diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/SiteInitializer.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/SiteInitializer.java index 6bbbd8f..ea4a3ea 100644 --- a/gerrit-war/src/main/java/com/google/gerrit/httpd/SiteInitializer.java +++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/SiteInitializer.java
@@ -20,7 +20,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -47,21 +48,19 @@ public void init() { try { if (sitePath != null) { - File site = new File(sitePath); - LOG.info(String.format("Initializing site at %s", - site.getAbsolutePath())); + Path site = Paths.get(sitePath); + LOG.info("Initializing site at " + site.toRealPath().normalize()); new BaseInit(site, false, true, pluginsDistribution, pluginsToInstall).run(); return; } try (Connection conn = connectToDb()) { - File site = getSiteFromReviewDb(conn); + Path site = getSiteFromReviewDb(conn); if (site == null && initPath != null) { - site = new File(initPath); + site = Paths.get(initPath); } if (site != null) { - LOG.info(String.format("Initializing site at %s", - site.getAbsolutePath())); + LOG.info("Initializing site at " + site.toRealPath().normalize()); new BaseInit(site, new ReviewDbDataSourceProvider(), false, false, pluginsDistribution, pluginsToInstall).run(); } @@ -76,12 +75,12 @@ return new ReviewDbDataSourceProvider().get().getConnection(); } - private File getSiteFromReviewDb(Connection conn) { + private Path getSiteFromReviewDb(Connection conn) { try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( "SELECT site_path FROM system_config")) { if (rs.next()) { - return new File(rs.getString(1)); + return Paths.get(rs.getString(1)); } } catch (SQLException e) { return null;
diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java index b97df3f..60f389e 100644 --- a/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java +++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java
@@ -22,12 +22,13 @@ import com.google.inject.Inject; import com.google.inject.Provider; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; -/** Provides {@link java.io.File} annotated with {@link SitePath}. */ -class SitePathFromSystemConfigProvider implements Provider<File> { - private final File path; +/** Provides {@link Path} annotated with {@link SitePath}. */ +class SitePathFromSystemConfigProvider implements Provider<Path> { + private final Path path; @Inject SitePathFromSystemConfigProvider(SchemaFactory<ReviewDb> schemaFactory) @@ -36,18 +37,18 @@ } @Override - public File get() { + public Path get() { return path; } - private static File read(SchemaFactory<ReviewDb> schemaFactory) + private static Path read(SchemaFactory<ReviewDb> schemaFactory) throws OrmException { ReviewDb db = schemaFactory.open(); try { List<SystemConfig> all = db.systemConfig().all().toList(); switch (all.size()) { case 1: - return new File(all.get(0).sitePath); + return Paths.get(all.get(0).sitePath); case 0: throw new OrmException("system_config table is empty"); default:
diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java index 15e2daa..eb4c792 100644 --- a/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java +++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java
@@ -78,8 +78,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -101,7 +102,7 @@ private static final Logger log = LoggerFactory.getLogger(WebAppInitializer.class); - private File sitePath; + private Path sitePath; private Injector dbInjector; private Injector cfgInjector; private Injector sysInjector; @@ -122,7 +123,7 @@ if (manager == null) { final String path = System.getProperty("gerrit.site_path"); if (path != null) { - sitePath = new File(path); + sitePath = Paths.get(path); } if (System.getProperty("gerrit.init") != null) { @@ -209,7 +210,7 @@ Module sitePathModule = new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toInstance(sitePath); + bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath); } }; modules.add(sitePathModule); @@ -261,7 +262,7 @@ modules.add(new AbstractModule() { @Override protected void configure() { - bind(File.class).annotatedWith(SitePath.class).toProvider( + bind(Path.class).annotatedWith(SitePath.class).toProvider( SitePathFromSystemConfigProvider.class).in(SINGLETON); } });
diff --git a/lib/BUCK b/lib/BUCK index a880f06..2760acc 100644 --- a/lib/BUCK +++ b/lib/BUCK
@@ -45,8 +45,8 @@ maven_jar( name = 'gson', - id = 'com.google.code.gson:gson:2.1', - sha1 = '2e66da15851f9f5b5079228f856c2f090ba98c38', + id = 'com.google.code.gson:gson:2.3.1', + sha1 = 'ecb6e1f8e4b0e84c4b886c2f14a1500caf309757', license = 'Apache2.0', )
diff --git a/lib/codemirror/BUCK b/lib/codemirror/BUCK index dc163c2..cfb43ff 100644 --- a/lib/codemirror/BUCK +++ b/lib/codemirror/BUCK
@@ -2,12 +2,19 @@ include_defs('//lib/codemirror/cm.defs') include_defs('//lib/codemirror/closure.defs') +REPO = GERRIT VERSION = 'd0a2ddaa04' SHA1 = '1df573141fcceec039d0260d2d66a5b15d663f9a' -URL = GERRIT + 'net/codemirror/codemirror-%s.zip' % VERSION -ZIP = 'codemirror-%s.zip' % VERSION -TOP = 'codemirror-%s' % VERSION +if REPO == MAVEN_CENTRAL: + URL = REPO + 'org/webjars/codemirror/%s/codemirror-%s.jar' % (VERSION, VERSION) + TOP = 'META-INF/resources/webjars/codemirror/%s' % VERSION + ZIP = 'codemirror-%s.jar' % VERSION +else: + URL = REPO + 'net/codemirror/codemirror-%s.zip' % VERSION + TOP = 'codemirror-%s' % VERSION + ZIP = 'codemirror-%s.zip' % VERSION + CLOSURE_VERSION = 'v20141120'
diff --git a/lib/jgit/BUCK b/lib/jgit/BUCK index 8b2088c..0027b3b 100644 --- a/lib/jgit/BUCK +++ b/lib/jgit/BUCK
@@ -1,13 +1,13 @@ include_defs('//lib/maven.defs') REPO = GERRIT # Leave here even if set to MAVEN_CENTRAL. -VERS = '3.6.2.201501210735-r.40-g23ad3a3' +VERS = '3.7.0.201502260915-r.33-g0f51246' maven_jar( name = 'jgit', id = 'org.eclipse.jgit:org.eclipse.jgit:' + VERS, - bin_sha1 = '849c10fec9a9af15f57651b99a5cf6de6bd3077c', - src_sha1 = '6fa857df4b73bf2fa222d3ad272e99e3c929453f', + bin_sha1 = '892fb364b52b32a717e350179ff6f230a1ead3a8', + src_sha1 = 'd41d18963b2907fb9e43bba619a7beb5fd631c16', license = 'jgit', repository = REPO, unsign = True, @@ -22,7 +22,7 @@ maven_jar( name = 'jgit-servlet', id = 'org.eclipse.jgit:org.eclipse.jgit.http.server:' + VERS, - sha1 = 'f4a2252fac9258479394a3be3318f88fc8a538e8', + sha1 = '35e5a3885194cbcdb308d431b8f3e3d4c8942872', license = 'jgit', repository = REPO, deps = [':jgit'], @@ -36,7 +36,7 @@ maven_jar( name = 'jgit-archive', id = 'org.eclipse.jgit:org.eclipse.jgit.archive:' + VERS, - sha1 = 'bb1cf790a4ca6760f99b1d86ad5d25857bf69dc2', + sha1 = 'c19445a08ed349b2b0df08cc92bd944b9e1494ce', license = 'jgit', repository = REPO, deps = [':jgit', @@ -53,7 +53,7 @@ maven_jar( name = 'junit', id = 'org.eclipse.jgit:org.eclipse.jgit.junit:' + VERS, - sha1 = '9b9f2da56aacde9e58f905becc4780b4d64ee79e', + sha1 = 'd4749f922109256b4f0cfcc004b5994c417abd9c', license = 'DO_NOT_DISTRIBUTE', repository = REPO, unsign = True,
diff --git a/lib/maven.defs b/lib/maven.defs index 4edba9c..cc45212 100644 --- a/lib/maven.defs +++ b/lib/maven.defs
@@ -46,9 +46,14 @@ from os import path parts = id.split(':') - if len(parts) != 3: - raise NameError('expected id="groupId:artifactId:version"') - group, artifact, version = parts + if len(parts) not in [3, 4]: + raise NameError('%s:\nexpected id="groupId:artifactId:version[:classifier]"' + % id) + if len(parts) == 4: + group, artifact, version, classifier = parts + else: + group, artifact, version = parts + classifier = None # SNAPSHOT artifacts are handled differently on Google storage bucket: # 'SNAPSHOT' is discarded from the directory name. However on other @@ -62,7 +67,11 @@ else: file_version = version + if classifier is not None: + file_version += '-' + classifier + jar = path.join(name, artifact.lower() + '-' + file_version) + url = '/'.join([ repository, group.replace('.', '/'), artifact, version,
diff --git a/plugins/commit-message-length-validator b/plugins/commit-message-length-validator index 7923b67..cee1dcd 160000 --- a/plugins/commit-message-length-validator +++ b/plugins/commit-message-length-validator
@@ -1 +1 @@ -Subproject commit 7923b67392164dcc65ada85f723fa5111b265484 +Subproject commit cee1dcd7bdfaa82e2e72ebc382ec13c393892125
diff --git a/plugins/cookbook-plugin b/plugins/cookbook-plugin index bb20992..de0c0d0 160000 --- a/plugins/cookbook-plugin +++ b/plugins/cookbook-plugin
@@ -1 +1 @@ -Subproject commit bb209927b3cfc3073ce5af81c4a8436068be9e0d +Subproject commit de0c0d019be1ce81b681ec4365bec169602c4b3c
diff --git a/plugins/replication b/plugins/replication index eded645..e9b9874 160000 --- a/plugins/replication +++ b/plugins/replication
@@ -1 +1 @@ -Subproject commit eded6451be8dc10945c110955d2bfcfe629eac32 +Subproject commit e9b987413e9bf59ced29f796e8c005161df47c1f
diff --git a/plugins/reviewnotes b/plugins/reviewnotes index ba82486..603b7b3 160000 --- a/plugins/reviewnotes +++ b/plugins/reviewnotes
@@ -1 +1 @@ -Subproject commit ba824869c6b24348647f26e04cf80e1ae82266ec +Subproject commit 603b7b3885a1d2953ca891f58d2a6095e72e5313
diff --git a/tools/build.defs b/tools/build.defs index 8b858cd..da07c1e 100644 --- a/tools/build.defs +++ b/tools/build.defs
@@ -71,8 +71,8 @@ context = [ '//gerrit-main:main_bin', '//gerrit-war:webapp_assets', - '//gerrit-gwtui:' + ui, - ] + context, + ] + (['//gerrit-gwtui:' + ui] if ui else []) + + context, docs = docs, visibility = visibility, )