Browse Source

Use consistent keys for repository cache lookups

tags/v1.6.1
James Moger 10 years ago
parent
commit
44c005e7c1

+ 73
- 23
src/main/java/com/gitblit/manager/RepositoryManager.java View File

@Override @Override
public void addToCachedRepositoryList(RepositoryModel model) { public void addToCachedRepositoryList(RepositoryModel model) {
if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) { if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
repositoryListCache.put(model.name.toLowerCase(), model);
String key = getRepositoryKey(model.name);
repositoryListCache.put(key, model);


// update the fork origin repository with this repository clone // update the fork origin repository with this repository clone
if (!StringUtils.isEmpty(model.originRepository)) { if (!StringUtils.isEmpty(model.originRepository)) {
String originKey = model.originRepository.toLowerCase();
String originKey = getRepositoryKey(model.originRepository);
if (repositoryListCache.containsKey(originKey)) { if (repositoryListCache.containsKey(originKey)) {
RepositoryModel origin = repositoryListCache.get(originKey); RepositoryModel origin = repositoryListCache.get(originKey);
origin.addFork(model.name); origin.addFork(model.name);
if (StringUtils.isEmpty(name)) { if (StringUtils.isEmpty(name)) {
return null; return null;
} }
return repositoryListCache.remove(name.toLowerCase());
String key = getRepositoryKey(name);
return repositoryListCache.remove(key);
} }


/** /**
// rebuild fork networks // rebuild fork networks
for (RepositoryModel model : repositoryListCache.values()) { for (RepositoryModel model : repositoryListCache.values()) {
if (!StringUtils.isEmpty(model.originRepository)) { if (!StringUtils.isEmpty(model.originRepository)) {
String originKey = model.originRepository.toLowerCase();
String originKey = getRepositoryKey(model.originRepository);
if (repositoryListCache.containsKey(originKey)) { if (repositoryListCache.containsKey(originKey)) {
RepositoryModel origin = repositoryListCache.get(originKey); RepositoryModel origin = repositoryListCache.get(originKey);
origin.addFork(model.name); origin.addFork(model.name);
/** /**
* Returns the JGit repository for the specified name. * Returns the JGit repository for the specified name.
* *
* @param repositoryName
* @param name
* @param logError * @param logError
* @return repository or null * @return repository or null
*/ */
@Override @Override
public Repository getRepository(String repositoryName, boolean logError) {
// Decode url-encoded repository name (issue-278)
// http://stackoverflow.com/questions/17183110
repositoryName = repositoryName.replace("%7E", "~").replace("%7e", "~");
public Repository getRepository(String name, boolean logError) {
String repositoryName = fixRepositoryName(name);


if (isCollectingGarbage(repositoryName)) { if (isCollectingGarbage(repositoryName)) {
logger.warn(MessageFormat.format("Rejecting request for {0}, busy collecting garbage!", repositoryName)); logger.warn(MessageFormat.format("Rejecting request for {0}, busy collecting garbage!", repositoryName));
* Returns the repository model for the specified repository. This method * Returns the repository model for the specified repository. This method
* does not consider user access permissions. * does not consider user access permissions.
* *
* @param repositoryName
* @param name
* @return repository model or null * @return repository model or null
*/ */
@Override @Override
public RepositoryModel getRepositoryModel(String repositoryName) {
// Decode url-encoded repository name (issue-278)
// http://stackoverflow.com/questions/17183110
repositoryName = repositoryName.replace("%7E", "~").replace("%7e", "~");
public RepositoryModel getRepositoryModel(String name) {
String repositoryName = fixRepositoryName(name);


String repositoryKey = repositoryName.toLowerCase();
String repositoryKey = getRepositoryKey(repositoryName);
if (!repositoryListCache.containsKey(repositoryKey)) { if (!repositoryListCache.containsKey(repositoryKey)) {
RepositoryModel model = loadRepositoryModel(repositoryName); RepositoryModel model = loadRepositoryModel(repositoryName);
if (model == null) { if (model == null) {
return count; return count;
} }


/**
* Replaces illegal character patterns in a repository name.
*
* @param repositoryName
* @return a corrected name
*/
private String fixRepositoryName(String repositoryName) {
if (StringUtils.isEmpty(repositoryName)) {
return repositoryName;
}

// Decode url-encoded repository name (issue-278)
// http://stackoverflow.com/questions/17183110
String name = repositoryName.replace("%7E", "~").replace("%7e", "~");
name = name.replace("%2F", "/").replace("%2f", "/");

if (name.charAt(name.length() - 1) == '/') {
name = name.substring(0, name.length() - 1);
}

// strip duplicate-slashes from requests for repositoryName (ticket-117, issue-454)
// specify first char as slash so we strip leading slashes
char lastChar = '/';
StringBuilder sb = new StringBuilder();
for (char c : name.toCharArray()) {
if (c == '/' && lastChar == c) {
continue;
}
sb.append(c);
lastChar = c;
}

return sb.toString();
}

/**
* Returns the cache key for the repository name.
*
* @param repositoryName
* @return the cache key for the repository
*/
private String getRepositoryKey(String repositoryName) {
String name = fixRepositoryName(repositoryName);
return StringUtils.stripDotGit(name).toLowerCase();
}

/** /**
* Workaround JGit. I need to access the raw config object directly in order * Workaround JGit. I need to access the raw config object directly in order
* to see if the config is dirty so that I can reload a repository model. * to see if the config is dirty so that I can reload a repository model.
if (!caseSensitiveCheck && settings.getBoolean(Keys.git.cacheRepositoryList, true)) { if (!caseSensitiveCheck && settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
// if we are caching use the cache to determine availability // if we are caching use the cache to determine availability
// otherwise we end up adding a phantom repository to the cache // otherwise we end up adding a phantom repository to the cache
return repositoryListCache.containsKey(repositoryName.toLowerCase());
String key = getRepositoryKey(repositoryName);
return repositoryListCache.containsKey(key);
} }
Repository r = getRepository(repositoryName, false); Repository r = getRepository(repositoryName, false);
if (r == null) { if (r == null) {
} }
String userProject = ModelUtils.getPersonalPath(username); String userProject = ModelUtils.getPersonalPath(username);
if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) { if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
String originKey = origin.toLowerCase();
String originKey = getRepositoryKey(origin);
String userPath = userProject + "/"; String userPath = userProject + "/";


// collect all origin nodes in fork network // collect all origin nodes in fork network
} }


if (originModel.originRepository != null) { if (originModel.originRepository != null) {
String ooKey = originModel.originRepository.toLowerCase();
String ooKey = getRepositoryKey(originModel.originRepository);
roots.add(ooKey); roots.add(ooKey);
originModel = repositoryListCache.get(ooKey); originModel = repositoryListCache.get(ooKey);
} else { } else {
if (repository.startsWith(userPath)) { if (repository.startsWith(userPath)) {
RepositoryModel model = repositoryListCache.get(repository); RepositoryModel model = repositoryListCache.get(repository);
if (!StringUtils.isEmpty(model.originRepository)) { if (!StringUtils.isEmpty(model.originRepository)) {
if (roots.contains(model.originRepository.toLowerCase())) {
String ooKey = getRepositoryKey(model.originRepository);
if (roots.contains(ooKey)) {
// user has a fork in this graph // user has a fork in this graph
return model.name; return model.name;
} }
public ForkModel getForkNetwork(String repository) { public ForkModel getForkNetwork(String repository) {
if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) { if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
// find the root, cached // find the root, cached
RepositoryModel model = repositoryListCache.get(repository.toLowerCase());
String key = getRepositoryKey(repository);
RepositoryModel model = repositoryListCache.get(key);
while (model.originRepository != null) { while (model.originRepository != null) {
model = repositoryListCache.get(model.originRepository.toLowerCase());
String originKey = getRepositoryKey(model.originRepository);
model = repositoryListCache.get(originKey);
} }
ForkModel root = getForkModelFromCache(model.name); ForkModel root = getForkModelFromCache(model.name);
return root; return root;
} }


private ForkModel getForkModelFromCache(String repository) { private ForkModel getForkModelFromCache(String repository) {
RepositoryModel model = repositoryListCache.get(repository.toLowerCase());
String key = getRepositoryKey(repository);
RepositoryModel model = repositoryListCache.get(key);
if (model == null) { if (model == null) {
return null; return null;
} }


// update this repository's origin's fork list // update this repository's origin's fork list
if (!StringUtils.isEmpty(repository.originRepository)) { if (!StringUtils.isEmpty(repository.originRepository)) {
RepositoryModel origin = repositoryListCache.get(repository.originRepository.toLowerCase());
String originKey = getRepositoryKey(repository.originRepository);
RepositoryModel origin = repositoryListCache.get(originKey);
if (origin != null && !ArrayUtils.isEmpty(origin.forks)) { if (origin != null && !ArrayUtils.isEmpty(origin.forks)) {
origin.forks.remove(repositoryName); origin.forks.remove(repositoryName);
origin.forks.add(repository.name); origin.forks.add(repository.name);

+ 3
- 0
src/main/java/com/gitblit/servlet/RawServlet.java View File

repository = path.substring(0, slash); repository = path.substring(0, slash);
} }
offset += slash; offset += slash;
if (offset == 0) {
offset++;
}
r = repositoryManager.getRepository(repository, false); r = repositoryManager.getRepository(repository, false);
if (repository.equals(path)) { if (repository.equals(path)) {
// either only repository in url or no repository found // either only repository in url or no repository found

+ 10
- 6
src/main/java/com/gitblit/wicket/pages/RepositoryPage.java View File

add(navigationPanel); add(navigationPanel);
add(new ExternalLink("syndication", SyndicationServlet.asLink(getRequest() add(new ExternalLink("syndication", SyndicationServlet.asLink(getRequest()
.getRelativePathPrefixToContextRoot(), repositoryName, null, 0)));
.getRelativePathPrefixToContextRoot(), getRepositoryName(), null, 0)));
// add floating search form // add floating search form
SearchForm searchForm = new SearchForm("searchForm", repositoryName);
SearchForm searchForm = new SearchForm("searchForm", getRepositoryName());
add(searchForm); add(searchForm);
searchForm.setTranslatedAttributes(); searchForm.setTranslatedAttributes();
private List<NavLink> registerNavLinks() { private List<NavLink> registerNavLinks() {
PageParameters params = null; PageParameters params = null;
if (!StringUtils.isEmpty(repositoryName)) { if (!StringUtils.isEmpty(repositoryName)) {
params = WicketUtils.newRepositoryParameter(repositoryName);
params = WicketUtils.newRepositoryParameter(getRepositoryName());
} }
List<NavLink> navLinks = new ArrayList<NavLink>(); List<NavLink> navLinks = new ArrayList<NavLink>();
navLinks.add(new PageNavLink("gb.commits", LogPage.class, params)); navLinks.add(new PageNavLink("gb.commits", LogPage.class, params));
navLinks.add(new PageNavLink("gb.tree", TreePage.class, params)); navLinks.add(new PageNavLink("gb.tree", TreePage.class, params));
if (app().tickets().isReady() && (app().tickets().isAcceptingNewTickets(model) || app().tickets().hasTickets(model))) { if (app().tickets().isReady() && (app().tickets().isAcceptingNewTickets(model) || app().tickets().hasTickets(model))) {
PageParameters tParams = WicketUtils.newOpenTicketsParameter(repositoryName);
PageParameters tParams = WicketUtils.newOpenTicketsParameter(getRepositoryName());
navLinks.add(new PageNavLink("gb.tickets", TicketsPage.class, tParams)); navLinks.add(new PageNavLink("gb.tickets", TicketsPage.class, tParams));
} }
navLinks.add(new PageNavLink("gb.docs", DocsPage.class, params, true)); navLinks.add(new PageNavLink("gb.docs", DocsPage.class, params, true));
// per-repository extra navlinks // per-repository extra navlinks
if (JGitUtils.getPagesBranch(r) != null) { if (JGitUtils.getPagesBranch(r) != null) {
ExternalNavLink pagesLink = new ExternalNavLink("gb.pages", PagesServlet.asLink( ExternalNavLink pagesLink = new ExternalNavLink("gb.pages", PagesServlet.asLink(
getRequest().getRelativePathPrefixToContextRoot(), repositoryName, null), true);
getRequest().getRelativePathPrefixToContextRoot(), getRepositoryName(), null), true);
navLinks.add(pagesLink); navLinks.add(pagesLink);
} }
return m; return m;
} }
protected String getRepositoryName() {
return getRepositoryModel().name;
}
protected RevCommit getCommit() { protected RevCommit getCommit() {
RevCommit commit = JGitUtils.getCommit(r, objectId); RevCommit commit = JGitUtils.getCommit(r, objectId);
if (commit == null) { if (commit == null) {
r = null; r = null;
} }
// setup page header and footer // setup page header and footer
setupPage(repositoryName, "/ " + getPageName());
setupPage(getRepositoryName(), "/ " + getPageName());
super.onBeforeRender(); super.onBeforeRender();
} }

Loading…
Cancel
Save