From eb0f7ea03074bb45c67d2ad877af3c5c85e6b3fc Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Mon, 03 Mar 2014 11:33:24 -0500 Subject: [PATCH] Fix compare page exception when a submodule changes (issue-375) --- src/main/java/com/gitblit/utils/JGitUtils.java | 143 ++++++++++++++++++++++++++++++++--------------- 1 files changed, 96 insertions(+), 47 deletions(-) diff --git a/src/main/java/com/gitblit/utils/JGitUtils.java b/src/main/java/com/gitblit/utils/JGitUtils.java index 75a4405..6a6085e 100644 --- a/src/main/java/com/gitblit/utils/JGitUtils.java +++ b/src/main/java/com/gitblit/utils/JGitUtils.java @@ -15,10 +15,8 @@ */ package com.gitblit.utils; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.text.DecimalFormat; import java.text.MessageFormat; import java.util.ArrayList; @@ -706,6 +704,7 @@ return null; } RevCommit commit = null; + RevWalk walk = null; try { // resolve object id ObjectId branchObject; @@ -714,12 +713,18 @@ } else { branchObject = repository.resolve(objectId); } - RevWalk walk = new RevWalk(repository); + if (branchObject == null) { + return null; + } + walk = new RevWalk(repository); RevCommit rev = walk.parseCommit(branchObject); commit = rev; - walk.dispose(); } catch (Throwable t) { error(t, repository, "{0} failed to get commit {1}", objectId); + } finally { + if (walk != null) { + walk.dispose(); + } } return commit; } @@ -755,18 +760,8 @@ ObjectId entid = tw.getObjectId(0); FileMode entmode = tw.getFileMode(0); if (entmode != FileMode.GITLINK) { - RevObject ro = rw.lookupAny(entid, entmode.getObjectType()); - rw.parseBody(ro); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - ObjectLoader ldr = repository.open(ro.getId(), Constants.OBJ_BLOB); - byte[] tmp = new byte[4096]; - InputStream in = ldr.openStream(); - int n; - while ((n = in.read(tmp)) > 0) { - os.write(tmp, 0, n); - } - in.close(); - content = os.toByteArray(); + ObjectLoader ldr = repository.open(entid, Constants.OBJ_BLOB); + content = ldr.getCachedBytes(); } } } catch (Throwable t) { @@ -810,17 +805,8 @@ byte[] content = null; try { RevBlob blob = rw.lookupBlob(ObjectId.fromString(objectId)); - rw.parseBody(blob); - ByteArrayOutputStream os = new ByteArrayOutputStream(); ObjectLoader ldr = repository.open(blob.getId(), Constants.OBJ_BLOB); - byte[] tmp = new byte[4096]; - InputStream in = ldr.openStream(); - int n; - while ((n = in.read(tmp)) > 0) { - os.write(tmp, 0, n); - } - in.close(); - content = os.toByteArray(); + content = ldr.getCachedBytes(); } catch (Throwable t) { error(t, repository, "{0} can't find blob {1}", objectId); } finally { @@ -990,6 +976,36 @@ * most recent commit. if null, HEAD is assumed. * @return list of files changed in a commit range */ + public static List<PathChangeModel> getFilesInRange(Repository repository, String startCommit, String endCommit) { + List<PathChangeModel> list = new ArrayList<PathChangeModel>(); + if (!hasCommits(repository)) { + return list; + } + try { + ObjectId startRange = repository.resolve(startCommit); + ObjectId endRange = repository.resolve(endCommit); + RevWalk rw = new RevWalk(repository); + RevCommit start = rw.parseCommit(startRange); + RevCommit end = rw.parseCommit(endRange); + list.addAll(getFilesInRange(repository, start, end)); + rw.release(); + } catch (Throwable t) { + error(t, repository, "{0} failed to determine files in range {1}..{2}!", startCommit, endCommit); + } + return list; + } + + /** + * Returns the list of files changed in a specified commit. If the + * repository does not exist or is empty, an empty list is returned. + * + * @param repository + * @param startCommit + * earliest commit + * @param endCommit + * most recent commit. if null, HEAD is assumed. + * @return list of files changed in a commit range + */ public static List<PathChangeModel> getFilesInRange(Repository repository, RevCommit startCommit, RevCommit endCommit) { List<PathChangeModel> list = new ArrayList<PathChangeModel>(); if (!hasCommits(repository)) { @@ -1003,7 +1019,7 @@ List<DiffEntry> diffEntries = df.scan(startCommit.getTree(), endCommit.getTree()); for (DiffEntry diff : diffEntries) { - PathChangeModel pcm = PathChangeModel.from(diff, null); + PathChangeModel pcm = PathChangeModel.from(diff, endCommit.getName()); list.add(pcm); } Collections.sort(list); @@ -1049,10 +1065,10 @@ List<TreeFilter> suffixFilters = new ArrayList<TreeFilter>(); for (String extension : extensions) { if (extension.charAt(0) == '.') { - suffixFilters.add(PathSuffixFilter.create("\\" + extension)); + suffixFilters.add(PathSuffixFilter.create(extension)); } else { // escape the . since this is a regexp filter - suffixFilters.add(PathSuffixFilter.create("\\." + extension)); + suffixFilters.add(PathSuffixFilter.create("." + extension)); } } TreeFilter filter; @@ -1470,23 +1486,6 @@ String target = null; try { target = repository.getFullBranch(); - if (!target.startsWith(Constants.R_HEADS)) { - // refers to an actual commit, probably a tag - // find latest tag that matches the commit, if any - List<RefModel> tagModels = getTags(repository, true, -1); - if (tagModels.size() > 0) { - RefModel tag = null; - Date lastDate = new Date(0); - for (RefModel tagModel : tagModels) { - if (tagModel.getReferencedObjectId().getName().equals(target) && - tagModel.getDate().after(lastDate)) { - tag = tagModel; - lastDate = tag.getDate(); - } - } - target = tag.getName(); - } - } } catch (Throwable t) { error(t, repository, "{0} failed to get symbolic HEAD target"); } @@ -1540,7 +1539,7 @@ */ public static boolean setBranchRef(Repository repository, String branch, String commitId) { String branchName = branch; - if (!branchName.startsWith(Constants.R_HEADS)) { + if (!branchName.startsWith(Constants.R_REFS)) { branchName = Constants.R_HEADS + branch; } @@ -2096,4 +2095,54 @@ } return StringUtils.decodeString(content); } + + /** + * Automatic repair of (some) invalid refspecs. These are the result of a + * bug in JGit cloning where a double forward-slash was injected. :( + * + * @param repository + * @return true, if the refspecs were repaired + */ + public static boolean repairFetchSpecs(Repository repository) { + StoredConfig rc = repository.getConfig(); + + // auto-repair broken fetch ref specs + for (String name : rc.getSubsections("remote")) { + int invalidSpecs = 0; + int repairedSpecs = 0; + List<String> specs = new ArrayList<String>(); + for (String spec : rc.getStringList("remote", name, "fetch")) { + try { + RefSpec rs = new RefSpec(spec); + // valid spec + specs.add(spec); + } catch (IllegalArgumentException e) { + // invalid spec + invalidSpecs++; + if (spec.contains("//")) { + // auto-repair this known spec bug + spec = spec.replace("//", "/"); + specs.add(spec); + repairedSpecs++; + } + } + } + + if (invalidSpecs == repairedSpecs && repairedSpecs > 0) { + // the fetch specs were automatically repaired + rc.setStringList("remote", name, "fetch", specs); + try { + rc.save(); + rc.load(); + LOGGER.debug("repaired {} invalid fetch refspecs for {}", repairedSpecs, repository.getDirectory()); + return true; + } catch (Exception e) { + LOGGER.error(null, e); + } + } else if (invalidSpecs > 0) { + LOGGER.error("mirror executor found {} invalid fetch refspecs for {}", invalidSpecs, repository.getDirectory()); + } + } + return false; + } } -- Gitblit v1.9.1