]> source.dussan.org Git - gitblit.git/commitdiff
fix for #967 filestore menu for all users 973/head
authorPaul Martin <paul@paulsputer.com>
Mon, 7 Dec 2015 23:09:26 +0000 (23:09 +0000)
committerPaul Martin <paul@paulsputer.com>
Mon, 7 Dec 2015 23:09:26 +0000 (23:09 +0000)
+ Filestore listing filtered by user view permissions
+ Configuration help for filestore relocated to website files
+ Added migration example

HOME.md
build.xml
src/main/java/com/gitblit/manager/FilestoreManager.java
src/main/java/com/gitblit/manager/GitblitManager.java
src/main/java/com/gitblit/manager/IFilestoreManager.java
src/main/java/com/gitblit/models/FilestoreModel.java
src/main/java/com/gitblit/wicket/pages/FilestorePage.java
src/main/java/com/gitblit/wicket/pages/FilestoreUsage.html
src/main/java/com/gitblit/wicket/pages/RootPage.java
src/site/setup_filestore.mkd [new file with mode: 0644]

diff --git a/HOME.md b/HOME.md
index 7c5449d33925c005c41bfaf756a4ceaf4758e28c..89527ee30a4d8df74b95417db0a2a0fd2c2a9db7 100644 (file)
--- a/HOME.md
+++ b/HOME.md
@@ -33,6 +33,8 @@ This documentation is the source content from which the [Gitblit website](http:/
 [[src/site/setup_viewer.mkd]]\r
 [[src/site/administration.mkd]]\r
 [[src/site/setup_scaling.mkd]]\r
+[[src/site/setup_filestore.mkd]]\r
+\r
 \r
 ### Gitblit Tickets\r
 \r
index c7dc499cb4f2515bb8cab46f54866cab74ca994b..7205bf8476ec49f830e671e75e79b8b6780e6725 100644 (file)
--- a/build.xml
+++ b/build.xml
                                                <page name="mirrors" src="setup_mirrors.mkd" />\r
                                                <page name="scaling" src="setup_scaling.mkd" />\r
                                                <page name="fail2ban" src="setup_fail2ban.mkd" />\r
+                                               <page name="filestore (Git LFS)" src="setup_filestore.mkd" />\r
                                                <divider />\r
                                                <page name="Gitblit as a viewer" src="setup_viewer.mkd" />\r
                                        </menu>\r
index fe65e2162329dc54a2d6b4a922b0a4f21135cbba..111085573869b89b43bad40108a8cbfb62653415 100644 (file)
@@ -77,6 +77,8 @@ public class FilestoreManager implements IFilestoreManager {
        private final Logger logger = LoggerFactory.getLogger(getClass());
 
        private final IRuntimeManager runtimeManager;
+       
+       private final IRepositoryManager repositoryManager;
 
        private final IStoredSettings settings;
 
@@ -93,8 +95,10 @@ public class FilestoreManager implements IFilestoreManager {
 
        @Inject
        FilestoreManager(
-                       IRuntimeManager runtimeManager) {
+                       IRuntimeManager runtimeManager,
+                       IRepositoryManager repositoryManager) {
                this.runtimeManager = runtimeManager;
+               this.repositoryManager = repositoryManager;
                this.settings = runtimeManager.getSettings();
        }
 
@@ -324,8 +328,29 @@ public class FilestoreManager implements IFilestoreManager {
        }
 
        @Override
-       public List<FilestoreModel> getAllObjects() {
-               return new ArrayList<FilestoreModel>(fileCache.values());
+       public List<FilestoreModel> getAllObjects(UserModel user) {
+               
+               final List<RepositoryModel> viewableRepositories = repositoryManager.getRepositoryModels(user);
+               List<String> viewableRepositoryNames = new ArrayList<String>(viewableRepositories.size());
+               
+               for (RepositoryModel repository : viewableRepositories) {
+                       viewableRepositoryNames.add(repository.name);
+               }
+               
+               if (viewableRepositoryNames.size() == 0) {
+                       return null;
+               }
+               
+               final Collection<FilestoreModel> allFiles = fileCache.values();
+               List<FilestoreModel> userViewableFiles = new ArrayList<FilestoreModel>(allFiles.size());
+               
+               for (FilestoreModel file : allFiles) {
+                       if (file.isInRepositoryList(viewableRepositoryNames)) {
+                               userViewableFiles.add(file);
+                       }
+               }
+               
+               return userViewableFiles;                               
        }
 
        @Override
index 4a385fc171563ad531a764117e80a3195aeb70e5..85d5c19faad3e4a99910635aa0d7b029a165533c 100644 (file)
@@ -1274,8 +1274,8 @@ public class GitblitManager implements IGitblit {
        }
        
        @Override
-       public List<FilestoreModel> getAllObjects() {
-               return filestoreManager.getAllObjects();
+       public List<FilestoreModel> getAllObjects(UserModel user) {
+               return filestoreManager.getAllObjects(user);
        }
        
        @Override
index 0720650c561fc7d9af42cd1836e11327e6b1770d..454331a3b20803105ebfeaa07567e704ec81a326 100644 (file)
@@ -37,7 +37,7 @@ public interface IFilestoreManager extends IManager {
        
        FilestoreModel.Status downloadBlob(String oid, UserModel user, RepositoryModel repo, OutputStream streamOut );
        
-       List<FilestoreModel> getAllObjects();
+       List<FilestoreModel> getAllObjects(UserModel user);
        
        File getStorageFolder();
        
index ff7b210ea96864ba0e0dc50f8b99c6f68f0188ee..4144df6b2403beff1f39302af948f68d420826c9 100644 (file)
@@ -111,6 +111,15 @@ public class FilestoreModel implements Serializable {
                repositories.remove(repo);
        }
        
+       public synchronized boolean isInRepositoryList(List<String> repoList) {
+               for (String name : repositories) {
+                       if (repoList.contains(name)) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+       
        public static enum Status {
 
                Deleted(-30),
index 97d5f25b7466a7c29d8a9f8f24a541b82fed00f8..be0181bf109f84e979e389f3936e748d2e988411 100644 (file)
@@ -18,6 +18,7 @@ package com.gitblit.wicket.pages;
 import java.text.DateFormat;
 import java.text.MessageFormat;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.io.FileUtils;
@@ -31,9 +32,12 @@ import org.apache.wicket.markup.repeater.data.ListDataProvider;
 import com.gitblit.Constants;
 import com.gitblit.models.FilestoreModel;
 import com.gitblit.models.UserModel;
+import com.gitblit.wicket.CacheControl;
 import com.gitblit.wicket.FilestoreUI;
+import com.gitblit.wicket.GitBlitWebSession;
 import com.gitblit.wicket.RequiresAdminRole;
 import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.CacheControl.LastModified;
 
 /**
  * Page to display the current status of the filestore.
@@ -41,17 +45,22 @@ import com.gitblit.wicket.WicketUtils;
  *
  * @author Paul Martin
  */
-@RequiresAdminRole
+@CacheControl(LastModified.ACTIVITY)
 public class FilestorePage extends RootPage {
 
        public FilestorePage() {
                super();
                setupPage("", "");
 
-               final List<FilestoreModel> files = app().filestore().getAllObjects();
+               final UserModel user = (GitBlitWebSession.get().getUser() == null) ? UserModel.ANONYMOUS : GitBlitWebSession.get().getUser();
                final long nBytesUsed = app().filestore().getFilestoreUsedByteCount();
                final long nBytesAvailable = app().filestore().getFilestoreAvailableByteCount();
+               List<FilestoreModel> files = app().filestore().getAllObjects(user);
 
+               if (files == null) {
+                       files = new ArrayList<FilestoreModel>();
+               }
+               
                String message = MessageFormat.format(getString("gb.filestoreStats"), files.size(),
                                FileUtils.byteCountToDisplaySize(nBytesUsed), FileUtils.byteCountToDisplaySize(nBytesAvailable) );
 
@@ -64,7 +73,6 @@ public class FilestorePage extends RootPage {
                helpLink.add(new Label("helpMessage", getString("gb.filestoreHelp")));
                add(helpLink);
 
-
                DataView<FilestoreModel> filesView = new DataView<FilestoreModel>("fileRow",
                                new ListDataProvider<FilestoreModel>(files)) {
                        private static final long serialVersionUID = 1L;
index e9bff47c56361c3f040b98bb7a9be6a6cff2626d..89e98cad1f08451a338371b5153062c4a7059b62 100644 (file)
 <div class="span10 offset1">   
        
        <div class="alert alert-danger">
-       <h3><center>Using the Filestore</center></h3>
+       <h3><center>Using the filestore</center></h3>
        <p>
-               <strong>All clients intending to use the filestore must first install the <a href="https://git-lfs.github.com/">Git-LFS Client</a> and then run <code>git lfs init</code> to register the hooks globally.</strong><br/>
-               <i>This version of GitBlit has been verified with Git-LFS client version 0.6.0 which requires Git v1.8.2 or higher.</i>
+               <strong>All clients intending to use the filestore must first install the <a href="https://git-lfs.github.com/">Git-LFS Client</a> and then run <code>git lfs install</code></strong><br/>
+               <p>
+               If using password authentication it is recommended that you configure the <a href="https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage">git credential storage</a> to avoid Git-LFS asking for your password on each file<br/>
+               On Windows for example: <code>git config --global credential.helper wincred</code>
+               </p>
        </p>
        </div>
                
        <h3>Clone</h3>
        <p>
-       Just <code>git clone</code> as usual, no further action is required as GitBlit is configured to use the default Git-LFS end point <code>{repository}/info/lfs/objects/</code>.<br/>
+       Just <code>git clone</code> as usual, no further action is required as Gitblit is configured to use the default Git-LFS end point <code>{repository}/info/lfs/objects/</code>.<br/>
        <i>If the repository uses a 3rd party Git-LFS server you will need to <a href="https://github.com/github/git-lfs/blob/master/docs/spec.md#the-server">manually configure the correct endpoints</a></i>.
        </p>
        
        <p><a href="https://github.com/github/git-lfs/blob/master/docs/spec.md">See the current Git-LFS specification for further details</a>.</p>
        <br />
        
-       <div class="alert alert-warn">
-       <h3><center>Limitations & Warnings</center></h3>
-       <p>GitBlit currently provides a server-only implementation of the opensource Git-LFS API, <a href="https://github.com/github/git-lfs/wiki/Implementations">other implementations</a> are available.<br/>
-       However, until <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=470333">JGit provides Git-LFS client capabilities</a> some GitBlit features may not be fully supported when using the filestore.
-       Notably:
-               <ul>
-               <li>Mirroring a repository that uses Git-LFS - Only the pointer files, not the large files, are mirrored.</li>
-               <li>Federation -  Only the pointer files, not the large files, are transfered.</li>
-               </ul>
-       </p>
-       </div>
-       
-       <div class="alert alert-info">
-       <h3><center>GitBlit Configuration</center></h3>
-       <p>GitBlit provides the following configuration items when using the filestore:
-               <h4>filestore.storageFolder</h4>
-               <p>Defines the path on the server where filestore objects are to be saved. This defaults to <code>${baseFolder}/lfs</code></p>
-               <h4>filestore.maxUploadSize</h4>
-               <p>Defines the maximum allowable size that can be uploaded to the filestore.  Once a file is uploaded it will be unaffected by later changes in this property. This defaults to <code>-1</code> indicating no limits.</p>
-       </p>
-       </div>
-       
+
 </div>
 </div>
 </div>
index 6ed5a357ba19f09a2b3eaa395395ec44d78c2a6e..12779ca262ef670aa46c0800b9b16261ba71cdf8 100644 (file)
@@ -197,9 +197,9 @@ public abstract class RootPage extends BasePage {
                        }
                        navLinks.add(new PageNavLink("gb.repositories", RepositoriesPage.class,
                                        getRootPageParameters()));
-                       if (user.canAdmin()) {
-                               navLinks.add(new PageNavLink("gb.filestore", FilestorePage.class, getRootPageParameters()));
-                       }
+                       
+                       navLinks.add(new PageNavLink("gb.filestore", FilestorePage.class, getRootPageParameters()));
+                               
                        navLinks.add(new PageNavLink("gb.activity", ActivityPage.class, getRootPageParameters()));
                        if (allowLucene) {
                                navLinks.add(new PageNavLink("gb.search", LuceneSearchPage.class));
diff --git a/src/site/setup_filestore.mkd b/src/site/setup_filestore.mkd
new file mode 100644 (file)
index 0000000..9ffc9c6
--- /dev/null
@@ -0,0 +1,61 @@
+## Configure Git Large File Storage
+
+Gitblit provides a filestore that supports the [Git Large File Storage (LFS) API](https://git-lfs.github.com/).
+
+### Server Configuration
+
+Gitblit is configured to work straight away.  However you may want to update the following in `gitblit.properties`:
+
+<table class="table">
+<thead>
+<tr><th>parameter</th><th>value</th><th>description</th></tr>
+</thead>
+<tbody>
+<tr>
+  <th>filestore.storageFolder</th><td>${baseFolder}/lfs</td>
+  <td>The path on the server where filestore objects are to be saved.</td>
+</tr>
+<tr>
+  <th>filestore.maxUploadSize</th><td>-1</td>
+  <td>The maximum allowable size that can be uploaded to the filestore.  Once a file is uploaded it will be unaffected by later changes in this property. The default of -1 indicates no limits.</td>
+</tr>
+</tbody>
+</table>
+
+       
+### Limitations
+
+Gitblit currently provides a server-only implementation of the opensource Git LFS API.
+
+1. Files in the filestore are not currently searchable by Lucene.
+2. Mirroring a repository that uses Git LFS will only mirror the pointer files, not the large files.
+3. Federation - Only the pointer files, not the large files, are transfered.
+
+Items 2 & 3 are pending [JGit Git LFS client capabilities](https://bugs.eclipse.org/bugs/show_bug.cgi?id=470333).
+
+
+### How does it work?
+
+1. Files that should be handled by Git LFS are defined in the `.gitattributes` file.
+2. Git LFS installs a pre-commit hook when installed `git lfs install`.
+3. When a commit is made the pre-commit hook replaces the defined Git LFS files with a pointer file containing metadata about the file so that it can be found later.
+4. When a commit is pushed, the changeset is sent to the git repository and the large files are sent to the filestore.   
+
+For further details check out the [Git LFS specification](https://github.com/github/git-lfs/blob/master/docs/spec.md).
+
+### Convert/Migrate existing repository
+
+It is possible to migrate an existing repository containing large files to one that leverages the filestore.  However, commit hash history will be altered.
+
+The following command may be run on a local repository:
+
+    git filter-branch --prune-empty --tree-filter '
+    git lfs track "*.docx" "*.pdf" > /dev/null
+    git add .gitattributes
+    git ls-files | xargs -d "\n" git check-attr filter | grep "filter: lfs" | sed -r "s/(.*): filter: lfs/\1/" | xargs -d "\n" -r bash -c "git rm -f --cached \"\$@\"; git add \"\$@\"" bash \
+    ' --tag-name-filter cat -- --all
+
+
+### Further Considerations
+
+While [other Git LFS implementations are available](https://github.com/github/git-lfs/wiki/Implementations) as there is no current [JGit LFS client capability](https://bugs.eclipse.org/bugs/show_bug.cgi?id=470333), Gitblit will be unable to access them.   
\ No newline at end of file