From 0adceb4b64dfe0dd509da33c6d733a47fbf803a2 Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Wed, 01 Aug 2012 21:21:32 -0400 Subject: [PATCH] Regex exclusions for repository search (issue 103) --- src/com/gitblit/utils/JGitUtils.java | 143 +++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 129 insertions(+), 14 deletions(-) diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java index 72e948c..9d2e471 100644 --- a/src/com/gitblit/utils/JGitUtils.java +++ b/src/com/gitblit/utils/JGitUtils.java @@ -20,7 +20,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.charset.Charset; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -30,12 +29,14 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.FetchCommand; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.diff.DiffEntry.ChangeType; import org.eclipse.jgit.diff.DiffFormatter; @@ -258,8 +259,12 @@ * @return Repository */ public static Repository createRepository(File repositoriesFolder, String name) { - Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(true).call(); - return git.getRepository(); + try { + Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(true).call(); + return git.getRepository(); + } catch (GitAPIException e) { + throw new RuntimeException(e); + } } /** @@ -271,16 +276,20 @@ * false all repositories are included. * @param searchSubfolders * recurse into subfolders to find grouped repositories + * @param depth + * optional recursion depth, -1 = infinite recursion + * @param exclusions + * list of regex exclusions for matching to folder names * @return list of repository names */ public static List<String> getRepositoryList(File repositoriesFolder, boolean onlyBare, - boolean searchSubfolders) { + boolean searchSubfolders, int depth, List<String> exclusions) { List<String> list = new ArrayList<String>(); if (repositoriesFolder == null || !repositoriesFolder.exists()) { return list; } list.addAll(getRepositoryList(repositoriesFolder.getAbsolutePath(), repositoriesFolder, - onlyBare, searchSubfolders)); + onlyBare, searchSubfolders, depth, exclusions)); StringUtils.sortRepositorynames(list); return list; } @@ -297,25 +306,61 @@ * repositories are included. * @param searchSubfolders * recurse into subfolders to find grouped repositories + * @param depth + * recursion depth, -1 = infinite recursion + * @param exclusions + * list of regex exclusions for matching to folder names * @return */ private static List<String> getRepositoryList(String basePath, File searchFolder, - boolean onlyBare, boolean searchSubfolders) { + boolean onlyBare, boolean searchSubfolders, int depth, List<String> exclusions) { File baseFile = new File(basePath); List<String> list = new ArrayList<String>(); + if (depth == 0) { + return list; + } + List<Pattern> patterns = new ArrayList<Pattern>(); + if (!ArrayUtils.isEmpty(exclusions)) { + for (String regex : exclusions) { + patterns.add(Pattern.compile(regex)); + } + } + + int nextDepth = (depth == -1) ? -1 : depth - 1; for (File file : searchFolder.listFiles()) { if (file.isDirectory()) { + boolean exclude = false; + for (Pattern pattern : patterns) { + String path = FileUtils.getRelativePath(baseFile, file).replace('\\', '/'); + if (pattern.matcher(path).find()) { + LOGGER.debug(MessageFormat.format("excluding {0} because of rule {1}", path, pattern.pattern())); + exclude = true; + break; + } + } + if (exclude) { + // skip to next file + continue; + } + File gitDir = FileKey.resolve(new File(searchFolder, file.getName()), FS.DETECTED); if (gitDir != null) { if (onlyBare && gitDir.getName().equals(".git")) { continue; } - // determine repository name relative to base path - String repository = FileUtils.getRelativePath(baseFile, file); - list.add(repository); + if (gitDir.equals(file) || gitDir.getParentFile().equals(file)) { + // determine repository name relative to base path + String repository = FileUtils.getRelativePath(baseFile, file); + list.add(repository); + } else if (searchSubfolders && file.canRead()) { + // look for repositories in subfolders + list.addAll(getRepositoryList(basePath, file, onlyBare, searchSubfolders, + nextDepth, exclusions)); + } } else if (searchSubfolders && file.canRead()) { // look for repositories in subfolders - list.addAll(getRepositoryList(basePath, file, onlyBare, searchSubfolders)); + list.addAll(getRepositoryList(basePath, file, onlyBare, searchSubfolders, + nextDepth, exclusions)); } } } @@ -543,14 +588,15 @@ * @param tree * if null, the RevTree from HEAD is assumed. * @param blobPath + * @param charsets optional * @return UTF-8 string content */ - public static String getStringContent(Repository repository, RevTree tree, String blobPath) { + public static String getStringContent(Repository repository, RevTree tree, String blobPath, String... charsets) { byte[] content = getByteContent(repository, tree, blobPath); if (content == null) { return null; } - return new String(content, Charset.forName(Constants.CHARACTER_ENCODING)); + return StringUtils.decodeString(content, charsets); } /** @@ -589,14 +635,15 @@ * * @param repository * @param objectId + * @param charsets optional * @return UTF-8 string content */ - public static String getStringContent(Repository repository, String objectId) { + public static String getStringContent(Repository repository, String objectId, String... charsets) { byte[] content = getByteContent(repository, objectId); if (content == null) { return null; } - return new String(content, Charset.forName(Constants.CHARACTER_ENCODING)); + return StringUtils.decodeString(content, charsets); } /** @@ -1223,6 +1270,74 @@ } /** + * Sets the local branch ref to point to the specified commit id. + * + * @param repository + * @param branch + * @param commitId + * @return true if successful + */ + public static boolean setBranchRef(Repository repository, String branch, String commitId) { + String branchName = branch; + if (!branchName.startsWith(Constants.R_HEADS)) { + branchName = Constants.R_HEADS + branch; + } + + try { + RefUpdate refUpdate = repository.updateRef(branchName, false); + refUpdate.setNewObjectId(ObjectId.fromString(commitId)); + RefUpdate.Result result = refUpdate.forceUpdate(); + + switch (result) { + case NEW: + case FORCED: + case NO_CHANGE: + case FAST_FORWARD: + return true; + default: + LOGGER.error(MessageFormat.format("{0} {1} update to {2} returned result {3}", + repository.getDirectory().getAbsolutePath(), branchName, commitId, result)); + } + } catch (Throwable t) { + error(t, repository, "{0} failed to set {1} to {2}", branchName, commitId); + } + return false; + } + + /** + * Deletes the specified branch ref. + * + * @param repository + * @param branch + * @return true if successful + */ + public static boolean deleteBranchRef(Repository repository, String branch) { + String branchName = branch; + if (!branchName.startsWith(Constants.R_HEADS)) { + branchName = Constants.R_HEADS + branch; + } + + try { + RefUpdate refUpdate = repository.updateRef(branchName, false); + refUpdate.setForceUpdate(true); + RefUpdate.Result result = refUpdate.delete(); + switch (result) { + case NEW: + case FORCED: + case NO_CHANGE: + case FAST_FORWARD: + return true; + default: + LOGGER.error(MessageFormat.format("{0} failed to delete to {1} returned result {2}", + repository.getDirectory().getAbsolutePath(), branchName, result)); + } + } catch (Throwable t) { + error(t, repository, "{0} failed to delete {1}", branchName); + } + return false; + } + + /** * Get the full branch and tag ref names for any potential HEAD targets. * * @param repository -- Gitblit v1.9.1