Merge branch 'stable-2.13'

* stable-2.13:
  Don't show 'LFS Options' header when LFS is not configured
  Update LFS documentation
  Add LFS Project settings to General project's page

Change-Id: I1b833797844ed91f168a4b49d157f12950453aa5
diff --git a/src/main/java/com/googlesource/gerrit/plugins/lfs/HttpModule.java b/src/main/java/com/googlesource/gerrit/plugins/lfs/HttpModule.java
index 03e3897..7997466 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/lfs/HttpModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/lfs/HttpModule.java
@@ -16,6 +16,9 @@
 
 import static com.google.gerrit.httpd.plugins.LfsPluginServlet.URL_REGEX;
 
+import com.google.gerrit.extensions.registration.DynamicSet;
+import com.google.gerrit.extensions.webui.JavaScriptPlugin;
+import com.google.gerrit.extensions.webui.WebUiPlugin;
 import com.google.gerrit.httpd.plugins.HttpPluginModule;
 import com.google.inject.Inject;
 
@@ -53,6 +56,9 @@
     for (LfsBackend backend : backends.values()) {
       populateRepository(backend);
     }
+
+    DynamicSet.bind(binder(), WebUiPlugin.class)
+      .toInstance(new JavaScriptPlugin("lfs-project-info.js"));
   }
 
   private void populateRepository(LfsBackend backend) {
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 91a02ef..602d566 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -82,6 +82,12 @@
 Note that regular git operations are not affected.
 If not set, defaults to `false`.
 
+lfs.backend
+: Backend that should be used for storing binaries. It has to be one of
+backends specified as [fs](#lfs-fs-backend) or [s3](#lfs-s3-backend) subsection
+of Global Plugin Settings. If not set, defaults to value of `storage.backend`
+from Global Plugin Settings.
+
 ## Global Plugin Settings
 
 The following options can be configured in `$GERRIT_SITE/etc/@PLUGIN@.config`
@@ -90,10 +96,10 @@
 ### Section `storage`
 
 storage.backend
-: The storage backend to use. Valid values are `fs` for local file system,
+: The default storage backend to use. Valid values are `fs` for local file system,
 and `s3` for Amazon S3. If not set, defaults to `fs`.
 
-### Section `fs`
+### <a id="lfs-fs-backend"></a>Section `fs` - default file system backend
 
 The following configuration options are only used when the backend is `fs`.
 
@@ -101,7 +107,7 @@
 : The directory in which to store data files. If not specified, defaults to
 the plugin's data folder: `$GERRIT_SITE/data/@PLUGIN@`.
 
-### Section `s3`
+### <a id="lfs-s3-backend"></a>Section `s3` - default S3 backend
 
 The following configuration options are only used when the backend is `s3`.
 
@@ -141,6 +147,29 @@
 [Amazon IAM secretKey] for authenticating to S3. It is recommended to place this
 setting in `$GERRIT_SITE/etc/@PLUGIN@.secure.config`.
 
+### Multiple LFS backends
+
+One can specify multiple LFS backends for both FS and S3 storage by introducing
+backend subsections:
+
+```
+  [fs "foo"]
+    directory = /foo_dir
+  [s3 "bar"]
+    ...
+```
+
+and use them for namespace configuration by adding backend namespace parameter:
+
+```
+  [@PLUGIN@ "sandbox/*"]
+    backend = foo
+    ...
+  [@PLUGIN@ "release/*"]
+    backend = bar
+    ...
+```
+
 ## Local Project Configuration
 
 The following options must be set in the local project's `.git/config` file.
diff --git a/src/main/resources/Documentation/rest-api.md b/src/main/resources/Documentation/rest-api.md
index 1c4fd28..5856e63 100644
--- a/src/main/resources/Documentation/rest-api.md
+++ b/src/main/resources/Documentation/rest-api.md
@@ -26,6 +26,8 @@
   {
     "enabled": true,
     "max_object_size": 102400
+    "read_only": true,
+    "backend": "foo"
   }
 ```
 
@@ -50,12 +52,16 @@
   Content-Type: application/json;charset=UTF-8
   )]}'
   {
-    "backend_type": "FS",
+    "default_backend_type": "FS",
+    "backends": {
+      "foo": "FS"
+    },
     "namespaces": {
       "test-project": {
         "enabled": true,
         "max_object_size": 102400,
-        "read_only": false
+        "read_only": false,
+        "backend": "foo"
       }
     }
   }
@@ -91,7 +97,10 @@
   Content-Type: application/json;charset=UTF-8
   )]}'
   {
-    "backend_type": "FS",
+    "default_backend_type": "FS",
+    "backends": {
+      "foo": "FS"
+    },
     "namespaces": {
       "test-project": {
         "enabled": false,
@@ -111,12 +120,16 @@
 _enabled_ is true. 0 means no limit is set.
 * _read_only_: Whether LFS is in read-only mode for this project. Only set when
 _enabled_ is true.
+* _backend_: LFS storage backend that is used by this project. Only set when
+_enabled_ is true.
 
 ### <a id="lfs-global-config-info"></a>LfsGlobalConfigInfo
 
 The `LfsGlobalConfigInfo` entity describes the global configuration for LFS.
 
-* _backend_type_: The LFS backend in use. Can be `FS` or `S3`.
+* _default_backend_type_: The default LFS backend in use. Can be `FS` or `S3`.
+* _backends_: List of storage backends that might be used in namespaces;
+map of backend name to storage type (either `FS` or `S3`).
 * _namespaces_: Configured namespaces as a map of [LfsProjectConfigInfo]
 (#lfs-project-config-info) entities.
 
diff --git a/src/main/resources/static/lfs-project-info.js b/src/main/resources/static/lfs-project-info.js
new file mode 100644
index 0000000..b514822
--- /dev/null
+++ b/src/main/resources/static/lfs-project-info.js
@@ -0,0 +1,69 @@
+// Copyright (C) 2016 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.
+
+Gerrit.install(function(self) {
+  function toUpperCamel(str) {
+    var words = str.split('_');
+    for (i=0; i<words.length; i++) {
+      words[i] = words[i].charAt(0).toUpperCase() + words[i].slice(1);
+    }
+    return words.join(' ');
+  }
+
+  function createRow(doc, name, value) {
+    var tr = doc.createElement('tr');
+    var td = doc.createElement('td');
+    td.appendChild(doc.createTextNode(toUpperCamel(name) + ':'));
+    tr.appendChild(td);
+    td = doc.createElement('td');
+    td.appendChild(doc.createTextNode(value));
+    tr.appendChild(td);
+    return tr;
+  }
+
+  function onProjectInfo(panel) {
+    var url = 'projects/'
+      + encodeURI(panel.p.PROJECT_NAME).replace(/\//g, '%2F') //escape slashes
+      + '/' + this.pluginName + '~'
+      + 'lfs:config-project';
+
+    Gerrit.get(url, function(lfs) {
+      // Don't show LFS header if nothing is configured
+      if (Object.getOwnPropertyNames(lfs).length < 1) {
+        return;
+      }
+
+      var doc = document;
+      // create header
+      var td = doc.createElement('td');
+      td.appendChild(Gerrit.html(
+        '<div class=\"smallHeading\">LFS Options</div>'));
+      var tr = doc.createElement('tr');
+      tr.appendChild(td);
+      var table = doc.createElement('table');
+      table.appendChild(tr);
+
+      // add all properties
+      for (var name in lfs) {
+        table.appendChild(createRow(doc, name, lfs[name]));
+      }
+
+      var frg = doc.createDocumentFragment();
+      frg.appendChild(table);
+      panel.body.appendChild(frg);
+    });
+  }
+
+  self.panel('PROJECT_INFO_SCREEN_BOTTOM', onProjectInfo);
+  });
\ No newline at end of file