Implement adjusting file permissions for shared repositories.

Implement adjusting file and directory permissions for shared
repositories in JGitUtils.
diff --git a/src/main/java/com/gitblit/utils/JGitUtils.java b/src/main/java/com/gitblit/utils/JGitUtils.java
index 03b54ee..49b3ad7 100644
--- a/src/main/java/com/gitblit/utils/JGitUtils.java
+++ b/src/main/java/com/gitblit/utils/JGitUtils.java
@@ -32,6 +32,7 @@
 import java.util.Map.Entry;

 import java.util.regex.Pattern;

 

+import org.apache.commons.io.filefilter.TrueFileFilter;

 import org.eclipse.jgit.api.CloneCommand;

 import org.eclipse.jgit.api.FetchCommand;

 import org.eclipse.jgit.api.Git;

@@ -260,12 +261,7 @@
 	 * @return Repository

 	 */

 	public static Repository createRepository(File repositoriesFolder, String name) {

-		try {

-			Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(true).call();

-			return git.getRepository();

-		} catch (GitAPIException e) {

-			throw new RuntimeException(e);

-		}

+		return createRepository(repositoriesFolder, name, "FALSE");

 	}

 

 	/**

@@ -279,7 +275,13 @@
 	 */

 	public static Repository createRepository(File repositoriesFolder, String name, String shared) {

 		try {

-			Repository repo = createRepository(repositoriesFolder, name);

+			Repository repo = null;

+			try {

+				Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(true).call();

+				repo = git.getRepository();

+			} catch (GitAPIException e) {

+				throw new RuntimeException(e);

+			}

 

 			GitConfigSharedRepository sharedRepository = new GitConfigSharedRepository(shared);

 			if (sharedRepository.isShared()) {

@@ -289,8 +291,12 @@
 				config.save();

 

 				if (! JnaUtils.isWindows()) {

-

-					//libc.chmod("/path/to/file", 0755);

+					Iterator<File> iter = org.apache.commons.io.FileUtils.iterateFilesAndDirs(repo.getDirectory(),

+							TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);

+					// Adjust permissions on file/directory

+					while (iter.hasNext()) {

+						adjustSharedPerm(iter.next(), sharedRepository);

+					}

 				}

 			}

 

@@ -299,7 +305,9 @@
 			throw new RuntimeException(e);

 		}

 	}

-	private enum GitConfigSharedRepositoryValue {

+

+	private enum GitConfigSharedRepositoryValue

+	{

 		UMASK("0", 0), FALSE("0", 0), OFF("0", 0), NO("0", 0),

 		GROUP("1", 0660), TRUE("1", 0660), ON("1", 0660), YES("1", 0660),

 		ALL("2", 0664), WORLD("2", 0664), EVERYBODY("2", 0664),

@@ -313,13 +321,13 @@
 		public int getPerm() { return permValue; };

 

 	}

+

 	private static class GitConfigSharedRepository

 	{

 		private int intValue;

-		GitConfigSharedRepositoryValue enumValue;

+		private GitConfigSharedRepositoryValue enumValue;

 

-		GitConfigSharedRepository(String s)

-		{

+		GitConfigSharedRepository(String s) {

 			if ( s == null || s.trim().isEmpty() ) {

 				enumValue = GitConfigSharedRepositoryValue.GROUP;

 			}

@@ -344,25 +352,61 @@
 			}

 		}

 

-		String getValue()

-		{

+		String getValue() {

 			if ( enumValue == GitConfigSharedRepositoryValue.Oxxx ) return Integer.toOctalString(intValue);

 			return enumValue.getConfigValue();

 		}

 

-		int getPerm()

-		{

+		int getPerm() {

 			if ( enumValue == GitConfigSharedRepositoryValue.Oxxx ) return intValue;

 			return enumValue.getPerm();

 		}

 

-		boolean isShared()

-		{

+		boolean isCustom() {

+			return enumValue == GitConfigSharedRepositoryValue.Oxxx;

+		}

+

+		boolean isShared() {

 			return (enumValue.getPerm() > 0) || enumValue == GitConfigSharedRepositoryValue.Oxxx;

 		}

 	}

 

 

+	public static int adjustSharedPerm(File path, String configShared) {

+		return adjustSharedPerm(path, new GitConfigSharedRepository(configShared));

+	}

+

+

+	public static int adjustSharedPerm(File path, GitConfigSharedRepository configShared) {

+		if (! configShared.isShared()) return 0;

+

+		int perm = configShared.getPerm();

+		int mode = JnaUtils.getFilemode(path);

+		if (mode < 0) return -1;

+

+		// If the owner has no write access, delete it from group and other, too.

+		if ((mode & JnaUtils.S_IWUSR) == 0) perm &= ~0222;

+		// If the owner has execute access, set it for all blocks that have read access.

+		if ((mode & JnaUtils.S_IXUSR) == JnaUtils.S_IXUSR) perm |= (perm & 0444) >> 2;

+

+		if (configShared.isCustom()) {

+			// Use the custom value for access permissions.

+			mode |= (mode & ~0777) | perm;

+		}

+		else {

+			// Just add necessary bits to existing permissions.

+			mode |= perm;

+		}

+

+		if (path.isDirectory()) {

+			mode |= (mode & 0444) >> 2;

+			mode |= JnaUtils.S_ISGID;

+		}

+

+		return JnaUtils.setFilemode(path, mode);

+	}

+

+

 	/**

 	 * Returns a list of repository names in the specified folder.

 	 * 

diff --git a/src/test/java/com/gitblit/tests/JGitUtilsTest.java b/src/test/java/com/gitblit/tests/JGitUtilsTest.java
index 4affca2..6f86b9f 100644
--- a/src/test/java/com/gitblit/tests/JGitUtilsTest.java
+++ b/src/test/java/com/gitblit/tests/JGitUtilsTest.java
@@ -52,6 +52,7 @@
 import com.gitblit.models.RefModel;

 import com.gitblit.utils.CompressionUtils;

 import com.gitblit.utils.JGitUtils;

+import com.gitblit.utils.JnaUtils;

 import com.gitblit.utils.StringUtils;

 

 public class JGitUtilsTest {

@@ -150,7 +151,7 @@
 

 	@Test

 	public void testCreateRepositoryShared() throws Exception {

-		String[] repositories = { "NewTestRepository.git", "NewTestRepository" };

+		String[] repositories = { "NewSharedTestRepository.git" };

 		for (String repositoryName : repositories) {

 			Repository repository = JGitUtils.createRepository(GitBlitSuite.REPOSITORIES,

 					repositoryName, "group");

@@ -159,13 +160,21 @@
 			assertNotNull(repository);

 			assertFalse(JGitUtils.hasCommits(repository));

 			assertNull(JGitUtils.getFirstCommit(repository, null));

-			assertEquals(folder.lastModified(), JGitUtils.getFirstChange(repository, null)

-					.getTime());

-			assertEquals(folder.lastModified(), JGitUtils.getLastChange(repository).when.getTime());

-			assertNull(JGitUtils.getCommit(repository, null));

+

+			assertTrue(folder.exists());

+			int mode = JnaUtils.getFilemode(folder);

+			assertEquals(JnaUtils.S_ISGID, mode & JnaUtils.S_ISGID);

+			assertEquals(JnaUtils.S_IRWXG, mode & JnaUtils.S_IRWXG);

+

+			mode = JnaUtils.getFilemode(folder.getAbsolutePath() + "/HEAD");

+			assertEquals(JnaUtils.S_IRGRP | JnaUtils.S_IWGRP, mode & JnaUtils.S_IRWXG);

+

+			mode = JnaUtils.getFilemode(folder.getAbsolutePath() + "/config");

+			assertEquals(JnaUtils.S_IRGRP | JnaUtils.S_IWGRP, mode & JnaUtils.S_IRWXG);

+

 			repository.close();

 			RepositoryCache.close(repository);

-//			FileUtils.delete(repository.getDirectory(), FileUtils.RECURSIVE);

+			FileUtils.delete(repository.getDirectory(), FileUtils.RECURSIVE);

 		}

 	}