The fork mechanism clones the repository , access restrictions, and other config options. The app has been updated throughout to handle personal repositories and to properly display origin/fork links. In order to fork a repository the user account must have the #fork role, the origin repository must permit forking, and the user account must have standard clone permissions to the repository. Because forking introduces a new user role no existing user accounts can automatically begin forking a repository. This is both a pro and a con. Since the fork has the same access restrictions as the origin repository, those who can access the origin may also access the fork. This is intentional to facilitate integration-manager workflow. The fork owner does have the power to completely change the access restrictions of his/her fork.tags/v1.2.0
<?xml version="1.0" encoding="UTF-8"?> | |||||
<projectDescription> | |||||
<name>gitblit</name> | |||||
<comment></comment> | |||||
<projects> | |||||
</projects> | |||||
<buildSpec> | |||||
<buildCommand> | |||||
<name>org.eclipse.jdt.core.javabuilder</name> | |||||
<arguments> | |||||
</arguments> | |||||
</buildCommand> | |||||
<buildCommand> | |||||
<name>net.sf.eclipsecs.core.CheckstyleBuilder</name> | |||||
<arguments> | |||||
</arguments> | |||||
</buildCommand> | |||||
</buildSpec> | |||||
<natures> | |||||
<nature>org.eclipse.jdt.core.javanature</nature> | |||||
<nature>net.sf.eclipsecs.core.CheckstyleNature</nature> | |||||
</natures> | |||||
</projectDescription> | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<projectDescription> | |||||
<name>Gitblit</name> | |||||
<comment></comment> | |||||
<projects> | |||||
</projects> | |||||
<buildSpec> | |||||
<buildCommand> | |||||
<name>org.eclipse.jdt.core.javabuilder</name> | |||||
<arguments> | |||||
</arguments> | |||||
</buildCommand> | |||||
<buildCommand> | |||||
<name>net.sf.eclipsecs.core.CheckstyleBuilder</name> | |||||
<arguments> | |||||
</arguments> | |||||
</buildCommand> | |||||
</buildSpec> | |||||
<natures> | |||||
<nature>org.eclipse.jdt.core.javanature</nature> | |||||
<nature>net.sf.eclipsecs.core.CheckstyleNature</nature> | |||||
</natures> | |||||
</projectDescription> |
#### additions | #### additions | ||||
- added support for X-Forwarded-Context for Apache subdomain proxy configurations (issue 135) | |||||
- delete branch feature (issue 121, Github/ajermakovics) | |||||
- added line links to blob view at the expense of zebra striping (issue 130) | |||||
- added RedmineUserService (github/mallowlabs) | |||||
- Added simple project pages. A project is a subfolder off the *git.repositoriesFolder*. | |||||
- Added support for personal repositories. This builds on the simple project pages. | |||||
Personal repositories are stored in *git.repositoriesFolder*/*~username*. Each user with personal repositories will have a user page, something like the GitHub profile page. Personal repositories have all the same features as common repositories. | |||||
- Added support for server-side forking of a repository to a personal repository (issue 137) | |||||
In order to fork a repository to a personal clone, the user account must have the *fork* permission **and** the repository must *allow forks*. The clone inherits the access restrictions of its origin. i.e. if Team A has access to the origin repository, then by default Team A also has access to the fork. This is to facilitate collaboration. However, the fork owner may change access to the fork and add/remove users/teams, etc as required. | |||||
- Added support for X-Forwarded-Context for Apache subdomain proxy configurations (issue 135) | |||||
- Delete branch feature (issue 121, Github/ajermakovics) | |||||
- Added line links to blob view at the expense of zebra striping (issue 130) | |||||
- Added RedmineUserService (github/mallowlabs) | |||||
#### changes | #### changes | ||||
### IDEAS | ### IDEAS | ||||
* Gitblit: Re-use the EGit branch visualization table cell renderer as some sort of servlet | * Gitblit: Re-use the EGit branch visualization table cell renderer as some sort of servlet | ||||
* Gitblit: Support personal repositories (~username/repo) | |||||
* Gitblit: diff should highlight inserted/removed fragment compared to original line | * Gitblit: diff should highlight inserted/removed fragment compared to original line | ||||
* Gitblit: implement branch permission controls as Groovy pre-receive script. | * Gitblit: implement branch permission controls as Groovy pre-receive script. | ||||
*Maintain permissions text file similar to a gitolite configuration file or svn authz file.* | *Maintain permissions text file similar to a gitolite configuration file or svn authz file.* |
outline: none; | outline: none; | ||||
} | } | ||||
[class^="icon-"], [class*=" icon-"] a i { | |||||
/* override for a links that look like bootstrap buttons */ | |||||
vertical-align: text-bottom; | |||||
} | |||||
hr { | hr { | ||||
margin-top: 10px; | margin-top: 10px; | ||||
margin-bottom: 10px; | margin-bottom: 10px; | ||||
font-weight: bold; | font-weight: bold; | ||||
} | } | ||||
.pageTitle { | |||||
color: #888; | |||||
font-size: 18px; | |||||
line-height: 27px; | |||||
} | |||||
.pageTitle .project, .pageTitle .repository { | |||||
font-family: Helvetica, arial, freesans, clean, sans-serif; | |||||
font-size: 22px; | |||||
} | |||||
.pageTitle .controls { | |||||
font-size: 12px; | |||||
} | |||||
.pageTitle .repository { | |||||
font-weight: bold; | |||||
} | |||||
.originRepository { | |||||
font-family: Helvetica, arial, freesans, clean, sans-serif; | |||||
color: #888; | |||||
font-size: 12px; | |||||
line-height: 14px; | |||||
margin: 0px; | |||||
} | |||||
.forkSource, .forkEntry { | |||||
color: #888; | |||||
} | |||||
.forkSource { | |||||
font-size: 18px; | |||||
line-height: 20px; | |||||
padding: 5px 0px; | |||||
} | |||||
.forkEntry { | |||||
font-size: 14px; | |||||
padding: 2px 0px; | |||||
} | |||||
div.page_footer { | div.page_footer { | ||||
clear: both; | clear: both; | ||||
height: 17px; | height: 17px; |
if (model.canAdmin) { | if (model.canAdmin) { | ||||
roles.add(Constants.ADMIN_ROLE); | roles.add(Constants.ADMIN_ROLE); | ||||
} | } | ||||
if (model.canFork) { | |||||
roles.add(Constants.FORK_ROLE); | |||||
} | |||||
if (model.excludeFromFederation) { | if (model.excludeFromFederation) { | ||||
roles.add(Constants.NOT_FEDERATED_ROLE); | roles.add(Constants.NOT_FEDERATED_ROLE); | ||||
} | } | ||||
Set<String> roles = new HashSet<String>(Arrays.asList(config.getStringList( | Set<String> roles = new HashSet<String>(Arrays.asList(config.getStringList( | ||||
USER, username, ROLE))); | USER, username, ROLE))); | ||||
user.canAdmin = roles.contains(Constants.ADMIN_ROLE); | user.canAdmin = roles.contains(Constants.ADMIN_ROLE); | ||||
user.canFork = roles.contains(Constants.FORK_ROLE); | |||||
user.excludeFromFederation = roles.contains(Constants.NOT_FEDERATED_ROLE); | user.excludeFromFederation = roles.contains(Constants.NOT_FEDERATED_ROLE); | ||||
// repository memberships | // repository memberships |
public static final String JGIT_VERSION = "JGit 2.1.0 (201209190230-r)"; | public static final String JGIT_VERSION = "JGit 2.1.0 (201209190230-r)"; | ||||
public static final String ADMIN_ROLE = "#admin"; | public static final String ADMIN_ROLE = "#admin"; | ||||
public static final String FORK_ROLE = "#fork"; | |||||
public static final String NOT_FEDERATED_ROLE = "#notfederated"; | public static final String NOT_FEDERATED_ROLE = "#notfederated"; | ||||
// Permissions | // Permissions | ||||
if (role.equalsIgnoreCase(Constants.ADMIN_ROLE)) { | if (role.equalsIgnoreCase(Constants.ADMIN_ROLE)) { | ||||
model.canAdmin = true; | model.canAdmin = true; | ||||
} else if (role.equalsIgnoreCase(Constants.FORK_ROLE)) { | |||||
model.canFork = true; | |||||
} else if (role.equalsIgnoreCase(Constants.NOT_FEDERATED_ROLE)) { | } else if (role.equalsIgnoreCase(Constants.NOT_FEDERATED_ROLE)) { | ||||
model.excludeFromFederation = true; | model.excludeFromFederation = true; | ||||
} | } | ||||
if (model.canAdmin) { | if (model.canAdmin) { | ||||
roles.add(Constants.ADMIN_ROLE); | roles.add(Constants.ADMIN_ROLE); | ||||
} | } | ||||
if (model.canFork) { | |||||
roles.add(Constants.FORK_ROLE); | |||||
} | |||||
if (model.excludeFromFederation) { | if (model.excludeFromFederation) { | ||||
roles.add(Constants.NOT_FEDERATED_ROLE); | roles.add(Constants.NOT_FEDERATED_ROLE); | ||||
} | } |
import java.io.InputStream; | import java.io.InputStream; | ||||
import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||
import java.lang.reflect.Field; | import java.lang.reflect.Field; | ||||
import java.net.URI; | |||||
import java.net.URISyntaxException; | |||||
import java.text.MessageFormat; | import java.text.MessageFormat; | ||||
import java.text.SimpleDateFormat; | import java.text.SimpleDateFormat; | ||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
private void addToCachedRepositoryList(String name, RepositoryModel model) { | private void addToCachedRepositoryList(String name, RepositoryModel model) { | ||||
if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) { | if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) { | ||||
repositoryListCache.put(name, model); | repositoryListCache.put(name, model); | ||||
// update the fork origin repository with this repository clone | |||||
if (!StringUtils.isEmpty(model.originRepository)) { | |||||
if (repositoryListCache.containsKey(model.originRepository)) { | |||||
RepositoryModel origin = repositoryListCache.get(model.originRepository); | |||||
origin.addFork(name); | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
* Removes the repository from the list of cached repositories. | * Removes the repository from the list of cached repositories. | ||||
* | * | ||||
* @param name | * @param name | ||||
* @return the model being removed | |||||
*/ | */ | ||||
private void removeFromCachedRepositoryList(String name) { | |||||
private RepositoryModel removeFromCachedRepositoryList(String name) { | |||||
if (StringUtils.isEmpty(name)) { | if (StringUtils.isEmpty(name)) { | ||||
return; | |||||
return null; | |||||
} | } | ||||
repositoryListCache.remove(name); | |||||
return repositoryListCache.remove(name); | |||||
} | } | ||||
/** | /** | ||||
if (model == null) { | if (model == null) { | ||||
return null; | return null; | ||||
} | } | ||||
addToCachedRepositoryList(repositoryName, model); | |||||
addToCachedRepositoryList(repositoryName, model); | |||||
return model; | return model; | ||||
} | } | ||||
* @return project config map | * @return project config map | ||||
*/ | */ | ||||
private Map<String, ProjectModel> getProjectConfigs() { | private Map<String, ProjectModel> getProjectConfigs() { | ||||
if (projectConfigs.isOutdated()) { | |||||
if (projectCache.isEmpty() || projectConfigs.isOutdated()) { | |||||
try { | try { | ||||
projectConfigs.load(); | projectConfigs.load(); | ||||
* Returns a list of project models for the user. | * Returns a list of project models for the user. | ||||
* | * | ||||
* @param user | * @param user | ||||
* @param includeUsers | |||||
* @return list of projects that are accessible to the user | * @return list of projects that are accessible to the user | ||||
*/ | */ | ||||
public List<ProjectModel> getProjectModels(UserModel user) { | |||||
public List<ProjectModel> getProjectModels(UserModel user, boolean includeUsers) { | |||||
Map<String, ProjectModel> configs = getProjectConfigs(); | Map<String, ProjectModel> configs = getProjectConfigs(); | ||||
// per-user project lists, this accounts for security and visibility | // per-user project lists, this accounts for security and visibility | ||||
} | } | ||||
// sort projects, root project first | // sort projects, root project first | ||||
List<ProjectModel> projects = new ArrayList<ProjectModel>(map.values()); | |||||
Collections.sort(projects); | |||||
projects.remove(map.get("")); | |||||
projects.add(0, map.get("")); | |||||
List<ProjectModel> projects; | |||||
if (includeUsers) { | |||||
// all projects | |||||
projects = new ArrayList<ProjectModel>(map.values()); | |||||
Collections.sort(projects); | |||||
projects.remove(map.get("")); | |||||
projects.add(0, map.get("")); | |||||
} else { | |||||
// all non-user projects | |||||
projects = new ArrayList<ProjectModel>(); | |||||
ProjectModel root = map.remove(""); | |||||
for (ProjectModel model : map.values()) { | |||||
if (!model.isUserProject()) { | |||||
projects.add(model); | |||||
} | |||||
} | |||||
Collections.sort(projects); | |||||
projects.add(0, root); | |||||
} | |||||
return projects; | return projects; | ||||
} | } | ||||
* @return a project model, or null if it does not exist | * @return a project model, or null if it does not exist | ||||
*/ | */ | ||||
public ProjectModel getProjectModel(String name, UserModel user) { | public ProjectModel getProjectModel(String name, UserModel user) { | ||||
for (ProjectModel project : getProjectModels(user)) { | |||||
for (ProjectModel project : getProjectModels(user, true)) { | |||||
if (project.name.equalsIgnoreCase(name)) { | if (project.name.equalsIgnoreCase(name)) { | ||||
return project; | return project; | ||||
} | } | ||||
Map<String, ProjectModel> configs = getProjectConfigs(); | Map<String, ProjectModel> configs = getProjectConfigs(); | ||||
ProjectModel project = configs.get(name.toLowerCase()); | ProjectModel project = configs.get(name.toLowerCase()); | ||||
if (project == null) { | if (project == null) { | ||||
return null; | |||||
project = new ProjectModel(name); | |||||
if (name.length() > 0 && name.charAt(0) == '~') { | |||||
UserModel user = getUserModel(name.substring(1)); | |||||
if (user != null) { | |||||
project.title = user.getDisplayName(); | |||||
project.description = "personal repositories"; | |||||
} | |||||
} | |||||
} else { | |||||
// clone the object | |||||
project = DeepCopier.copy(project); | |||||
} | } | ||||
// clone the object | |||||
project = DeepCopier.copy(project); | |||||
String folder = name.toLowerCase() + "/"; | |||||
for (String repository : getRepositoryList()) { | |||||
if (repository.toLowerCase().startsWith(folder)) { | |||||
project.addRepository(repository); | |||||
if (StringUtils.isEmpty(name)) { | |||||
// get root repositories | |||||
for (String repository : getRepositoryList()) { | |||||
if (repository.indexOf('/') == -1) { | |||||
project.addRepository(repository); | |||||
} | |||||
} | } | ||||
} else { | |||||
// get repositories in subfolder | |||||
String folder = name.toLowerCase() + "/"; | |||||
for (String repository : getRepositoryList()) { | |||||
if (repository.toLowerCase().startsWith(folder)) { | |||||
project.addRepository(repository); | |||||
} | |||||
} | |||||
} | |||||
if (project.repositories.size() == 0) { | |||||
// no repositories == no project | |||||
return null; | |||||
} | } | ||||
return project; | return project; | ||||
} | } | ||||
model.hasCommits = JGitUtils.hasCommits(r); | model.hasCommits = JGitUtils.hasCommits(r); | ||||
model.lastChange = JGitUtils.getLastChange(r); | model.lastChange = JGitUtils.getLastChange(r); | ||||
model.isBare = r.isBare(); | model.isBare = r.isBare(); | ||||
if (repositoryName.indexOf('/') == -1) { | |||||
model.projectPath = ""; | |||||
} else { | |||||
model.projectPath = repositoryName.substring(0, repositoryName.indexOf('/')); | |||||
} | |||||
StoredConfig config = r.getConfig(); | StoredConfig config = r.getConfig(); | ||||
boolean hasOrigin = !StringUtils.isEmpty(config.getString("remote", "origin", "url")); | |||||
if (config != null) { | if (config != null) { | ||||
model.description = getConfig(config, "description", ""); | model.description = getConfig(config, "description", ""); | ||||
model.owner = getConfig(config, "owner", ""); | model.owner = getConfig(config, "owner", ""); | ||||
model.useTickets = getConfig(config, "useTickets", false); | model.useTickets = getConfig(config, "useTickets", false); | ||||
model.useDocs = getConfig(config, "useDocs", false); | model.useDocs = getConfig(config, "useDocs", false); | ||||
model.allowForks = getConfig(config, "allowForks", true); | |||||
model.accessRestriction = AccessRestrictionType.fromName(getConfig(config, | model.accessRestriction = AccessRestrictionType.fromName(getConfig(config, | ||||
"accessRestriction", settings.getString(Keys.git.defaultAccessRestriction, null))); | "accessRestriction", settings.getString(Keys.git.defaultAccessRestriction, null))); | ||||
model.authorizationControl = AuthorizationControl.fromName(getConfig(config, | model.authorizationControl = AuthorizationControl.fromName(getConfig(config, | ||||
"authorizationControl", settings.getString(Keys.git.defaultAuthorizationControl, null))); | "authorizationControl", settings.getString(Keys.git.defaultAuthorizationControl, null))); | ||||
model.showRemoteBranches = getConfig(config, "showRemoteBranches", false); | |||||
model.showRemoteBranches = getConfig(config, "showRemoteBranches", hasOrigin); | |||||
model.isFrozen = getConfig(config, "isFrozen", false); | model.isFrozen = getConfig(config, "isFrozen", false); | ||||
model.showReadme = getConfig(config, "showReadme", false); | model.showReadme = getConfig(config, "showReadme", false); | ||||
model.skipSizeCalculation = getConfig(config, "skipSizeCalculation", false); | model.skipSizeCalculation = getConfig(config, "skipSizeCalculation", false); | ||||
model.HEAD = JGitUtils.getHEADRef(r); | model.HEAD = JGitUtils.getHEADRef(r); | ||||
model.availableRefs = JGitUtils.getAvailableHeadTargets(r); | model.availableRefs = JGitUtils.getAvailableHeadTargets(r); | ||||
r.close(); | r.close(); | ||||
if (model.origin != null && model.origin.startsWith("file://")) { | |||||
// repository was cloned locally... perhaps as a fork | |||||
try { | |||||
File folder = new File(new URI(model.origin)); | |||||
String originRepo = com.gitblit.utils.FileUtils.getRelativePath(getRepositoriesFolder(), folder); | |||||
if (!StringUtils.isEmpty(originRepo)) { | |||||
// ensure origin still exists | |||||
File repoFolder = new File(getRepositoriesFolder(), originRepo); | |||||
if (repoFolder.exists()) { | |||||
model.originRepository = originRepo; | |||||
} | |||||
} | |||||
} catch (URISyntaxException e) { | |||||
logger.error("Failed to determine fork for " + model, e); | |||||
} | |||||
} | |||||
return model; | return model; | ||||
} | } | ||||
"Failed to rename repository permissions ''{0}'' to ''{1}''.", | "Failed to rename repository permissions ''{0}'' to ''{1}''.", | ||||
repositoryName, repository.name)); | repositoryName, repository.name)); | ||||
} | } | ||||
// rename fork origins in their configs | |||||
if (!ArrayUtils.isEmpty(repository.forks)) { | |||||
for (String fork : repository.forks) { | |||||
Repository rf = getRepository(fork); | |||||
try { | |||||
StoredConfig config = rf.getConfig(); | |||||
String origin = config.getString("remote", "origin", "url"); | |||||
origin = origin.replace(repositoryName, repository.name); | |||||
config.setString("remote", "origin", "url", origin); | |||||
config.save(); | |||||
} catch (Exception e) { | |||||
logger.error("Failed to update repository fork config for " + fork, e); | |||||
} | |||||
rf.close(); | |||||
} | |||||
} | |||||
// clear the cache | // clear the cache | ||||
clearRepositoryMetadataCache(repositoryName); | clearRepositoryMetadataCache(repositoryName); | ||||
repository.resetDisplayName(); | |||||
} | } | ||||
// load repository | // load repository | ||||
config.setString(Constants.CONFIG_GITBLIT, null, "owner", repository.owner); | config.setString(Constants.CONFIG_GITBLIT, null, "owner", repository.owner); | ||||
config.setBoolean(Constants.CONFIG_GITBLIT, null, "useTickets", repository.useTickets); | config.setBoolean(Constants.CONFIG_GITBLIT, null, "useTickets", repository.useTickets); | ||||
config.setBoolean(Constants.CONFIG_GITBLIT, null, "useDocs", repository.useDocs); | config.setBoolean(Constants.CONFIG_GITBLIT, null, "useDocs", repository.useDocs); | ||||
config.setBoolean(Constants.CONFIG_GITBLIT, null, "allowForks", repository.allowForks); | |||||
config.setString(Constants.CONFIG_GITBLIT, null, "accessRestriction", repository.accessRestriction.name()); | config.setString(Constants.CONFIG_GITBLIT, null, "accessRestriction", repository.accessRestriction.name()); | ||||
config.setString(Constants.CONFIG_GITBLIT, null, "authorizationControl", repository.authorizationControl.name()); | config.setString(Constants.CONFIG_GITBLIT, null, "authorizationControl", repository.authorizationControl.name()); | ||||
config.setBoolean(Constants.CONFIG_GITBLIT, null, "showRemoteBranches", repository.showRemoteBranches); | config.setBoolean(Constants.CONFIG_GITBLIT, null, "showRemoteBranches", repository.showRemoteBranches); | ||||
closeRepository(repositoryName); | closeRepository(repositoryName); | ||||
// clear the repository cache | // clear the repository cache | ||||
clearRepositoryMetadataCache(repositoryName); | clearRepositoryMetadataCache(repositoryName); | ||||
removeFromCachedRepositoryList(repositoryName); | |||||
RepositoryModel model = removeFromCachedRepositoryList(repositoryName); | |||||
if (!ArrayUtils.isEmpty(model.forks)) { | |||||
resetRepositoryListCache(); | |||||
} | |||||
File folder = new File(repositoriesFolder, repositoryName); | File folder = new File(repositoriesFolder, repositoryName); | ||||
if (folder.exists() && folder.isDirectory()) { | if (folder.exists() && folder.isDirectory()) { | ||||
scheduledExecutor.shutdownNow(); | scheduledExecutor.shutdownNow(); | ||||
luceneExecutor.close(); | luceneExecutor.close(); | ||||
} | } | ||||
/** | |||||
* Creates a personal fork of the specified repository. The clone is view | |||||
* restricted by default and the owner of the source repository is given | |||||
* access to the clone. | |||||
* | |||||
* @param repository | |||||
* @param user | |||||
* @return true, if successful | |||||
*/ | |||||
public boolean fork(RepositoryModel repository, UserModel user) { | |||||
String cloneName = MessageFormat.format("~{0}/{1}.git", user.username, StringUtils.stripDotGit(StringUtils.getLastPathElement(repository.name))); | |||||
String fromUrl = MessageFormat.format("file://{0}/{1}", repositoriesFolder.getAbsolutePath(), repository.name); | |||||
try { | |||||
// clone the repository | |||||
JGitUtils.cloneRepository(repositoriesFolder, cloneName, fromUrl, true, null); | |||||
// create a Gitblit repository model for the clone | |||||
RepositoryModel cloneModel = repository.cloneAs(cloneName); | |||||
cloneModel.owner = user.username; | |||||
updateRepositoryModel(cloneName, cloneModel, false); | |||||
if (AuthorizationControl.NAMED.equals(cloneModel.authorizationControl)) { | |||||
// add the owner of the source repository to the clone's access list | |||||
if (!StringUtils.isEmpty(repository.owner)) { | |||||
UserModel owner = getUserModel(repository.owner); | |||||
if (owner != null) { | |||||
owner.repositories.add(cloneName); | |||||
updateUserModel(owner.username, owner, false); | |||||
} | |||||
} | |||||
// inherit origin's access lists | |||||
List<String> users = getRepositoryUsers(repository); | |||||
setRepositoryUsers(cloneModel, users); | |||||
List<String> teams = getRepositoryTeams(repository); | |||||
setRepositoryTeams(cloneModel, teams); | |||||
} | |||||
// add this clone to the cached model | |||||
addToCachedRepositoryList(cloneModel.name, cloneModel); | |||||
return true; | |||||
} catch (Exception e) { | |||||
logger.error("failed to fork", e); | |||||
} | |||||
return false; | |||||
} | |||||
} | } |
commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType, | commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType, | ||||
offset, length); | offset, length); | ||||
} | } | ||||
Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository); | |||||
Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository, model.showRemoteBranches); | |||||
// convert RevCommit to SyndicatedEntryModel | // convert RevCommit to SyndicatedEntryModel | ||||
for (RevCommit commit : commits) { | for (RevCommit commit : commits) { |
this.title = ""; | this.title = ""; | ||||
this.description = ""; | this.description = ""; | ||||
} | } | ||||
public boolean isUserProject() { | |||||
return name.charAt(0) == '~'; | |||||
} | |||||
public boolean hasRepository(String name) { | public boolean hasRepository(String name) { | ||||
return repositories.contains(name.toLowerCase()); | return repositories.contains(name.toLowerCase()); |
import java.util.Date; | import java.util.Date; | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.Set; | |||||
import java.util.TreeSet; | |||||
import com.gitblit.Constants.AccessRestrictionType; | import com.gitblit.Constants.AccessRestrictionType; | ||||
import com.gitblit.Constants.AuthorizationControl; | import com.gitblit.Constants.AuthorizationControl; | ||||
public List<String> postReceiveScripts; | public List<String> postReceiveScripts; | ||||
public List<String> mailingLists; | public List<String> mailingLists; | ||||
public Map<String, String> customFields; | public Map<String, String> customFields; | ||||
public String projectPath; | |||||
private String displayName; | private String displayName; | ||||
public boolean allowForks; | |||||
public Set<String> forks; | |||||
public String originRepository; | |||||
public RepositoryModel() { | public RepositoryModel() { | ||||
this("", "", "", new Date(0)); | this("", "", "", new Date(0)); | ||||
} | } | ||||
return localBranches; | return localBranches; | ||||
} | } | ||||
public void addFork(String repository) { | |||||
if (forks == null) { | |||||
forks = new TreeSet<String>(); | |||||
} | |||||
forks.add(repository); | |||||
} | |||||
public void removeFork(String repository) { | |||||
if (forks == null) { | |||||
return; | |||||
} | |||||
forks.remove(repository); | |||||
} | |||||
public void resetDisplayName() { | |||||
displayName = null; | |||||
} | |||||
@Override | @Override | ||||
public String toString() { | public String toString() { | ||||
public int compareTo(RepositoryModel o) { | public int compareTo(RepositoryModel o) { | ||||
return StringUtils.compareRepositoryNames(name, o.name); | return StringUtils.compareRepositoryNames(name, o.name); | ||||
} | } | ||||
public boolean isPersonalRepository() { | |||||
return !StringUtils.isEmpty(projectPath) && projectPath.charAt(0) == '~'; | |||||
} | |||||
public boolean isUsersPersonalRepository(String username) { | |||||
return !StringUtils.isEmpty(projectPath) && projectPath.equalsIgnoreCase("~" + username); | |||||
} | |||||
public RepositoryModel cloneAs(String cloneName) { | |||||
RepositoryModel clone = new RepositoryModel(); | |||||
clone.name = cloneName; | |||||
clone.description = description; | |||||
clone.accessRestriction = accessRestriction; | |||||
clone.authorizationControl = authorizationControl; | |||||
clone.federationStrategy = federationStrategy; | |||||
clone.showReadme = showReadme; | |||||
clone.showRemoteBranches = false; | |||||
clone.allowForks = false; | |||||
clone.useDocs = useDocs; | |||||
clone.useTickets = useTickets; | |||||
clone.skipSizeCalculation = skipSizeCalculation; | |||||
clone.skipSummaryMetrics = skipSummaryMetrics; | |||||
return clone; | |||||
} | |||||
} | } |
import java.util.HashSet; | import java.util.HashSet; | ||||
import java.util.Set; | import java.util.Set; | ||||
import com.gitblit.Constants.AccessRestrictionType; | |||||
import com.gitblit.Constants.AuthorizationControl; | import com.gitblit.Constants.AuthorizationControl; | ||||
import com.gitblit.utils.StringUtils; | import com.gitblit.utils.StringUtils; | ||||
public String displayName; | public String displayName; | ||||
public String emailAddress; | public String emailAddress; | ||||
public boolean canAdmin; | public boolean canAdmin; | ||||
public boolean canFork; | |||||
public boolean excludeFromFederation; | public boolean excludeFromFederation; | ||||
public final Set<String> repositories = new HashSet<String>(); | public final Set<String> repositories = new HashSet<String>(); | ||||
public final Set<TeamModel> teams = new HashSet<TeamModel>(); | public final Set<TeamModel> teams = new HashSet<TeamModel>(); | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
public boolean canForkRepository(RepositoryModel repository) { | |||||
if (canAdmin) { | |||||
return true; | |||||
} | |||||
if (!canFork) { | |||||
// user has been prohibited from forking | |||||
return false; | |||||
} | |||||
if (!isAuthenticated) { | |||||
// unauthenticated user model | |||||
return false; | |||||
} | |||||
if (("~" + username).equalsIgnoreCase(repository.projectPath)) { | |||||
// this repository is already a personal repository | |||||
return false; | |||||
} | |||||
if (!repository.allowForks) { | |||||
// repository prohibits forks | |||||
return false; | |||||
} | |||||
if (repository.accessRestriction.atLeast(AccessRestrictionType.CLONE)) { | |||||
return canAccessRepository(repository); | |||||
} | |||||
// repository is not clone-restricted | |||||
return true; | |||||
} | |||||
public boolean hasRepository(String name) { | public boolean hasRepository(String name) { | ||||
return repositories.contains(name.toLowerCase()); | return repositories.contains(name.toLowerCase()); |
branches.add(objectId); | branches.add(objectId); | ||||
} | } | ||||
Map<ObjectId, List<RefModel>> allRefs = JGitUtils | Map<ObjectId, List<RefModel>> allRefs = JGitUtils | ||||
.getAllRefs(repository); | |||||
.getAllRefs(repository, model.showRemoteBranches); | |||||
for (String branch : branches) { | for (String branch : branches) { | ||||
String shortName = branch; | String shortName = branch; |
* @return all refs grouped by their referenced object id | * @return all refs grouped by their referenced object id | ||||
*/ | */ | ||||
public static Map<ObjectId, List<RefModel>> getAllRefs(Repository repository) { | public static Map<ObjectId, List<RefModel>> getAllRefs(Repository repository) { | ||||
return getAllRefs(repository, true); | |||||
} | |||||
/** | |||||
* Returns all refs grouped by their associated object id. | |||||
* | |||||
* @param repository | |||||
* @param includeRemoteRefs | |||||
* @return all refs grouped by their referenced object id | |||||
*/ | |||||
public static Map<ObjectId, List<RefModel>> getAllRefs(Repository repository, boolean includeRemoteRefs) { | |||||
List<RefModel> list = getRefs(repository, org.eclipse.jgit.lib.RefDatabase.ALL, true, -1); | List<RefModel> list = getRefs(repository, org.eclipse.jgit.lib.RefDatabase.ALL, true, -1); | ||||
Map<ObjectId, List<RefModel>> refs = new HashMap<ObjectId, List<RefModel>>(); | Map<ObjectId, List<RefModel>> refs = new HashMap<ObjectId, List<RefModel>>(); | ||||
for (RefModel ref : list) { | for (RefModel ref : list) { | ||||
if (!includeRemoteRefs && ref.getName().startsWith(Constants.R_REMOTES)) { | |||||
continue; | |||||
} | |||||
ObjectId objectid = ref.getReferencedObjectId(); | ObjectId objectid = ref.getReferencedObjectId(); | ||||
if (!refs.containsKey(objectid)) { | if (!refs.containsKey(objectid)) { | ||||
refs.put(objectid, new ArrayList<RefModel>()); | refs.put(objectid, new ArrayList<RefModel>()); |
* @return the first invalid character found or null if string is acceptable | * @return the first invalid character found or null if string is acceptable | ||||
*/ | */ | ||||
public static Character findInvalidCharacter(String name) { | public static Character findInvalidCharacter(String name) { | ||||
char[] validChars = { '/', '.', '_', '-' }; | |||||
char[] validChars = { '/', '.', '_', '-', '~' }; | |||||
for (char c : name.toCharArray()) { | for (char c : name.toCharArray()) { | ||||
if (!Character.isLetterOrDigit(c)) { | if (!Character.isLetterOrDigit(c)) { | ||||
boolean ok = false; | boolean ok = false; | ||||
} | } | ||||
return input; | return input; | ||||
} | } | ||||
/** | |||||
* Returns the first path element of a path string. If no path separator is | |||||
* found in the path, an empty string is returned. | |||||
* | |||||
* @param path | |||||
* @return the first element in the path | |||||
*/ | |||||
public static String getFirstPathElement(String path) { | |||||
if (path.indexOf('/') > -1) { | |||||
return path.substring(0, path.indexOf('/')).trim(); | |||||
} | |||||
return ""; | |||||
} | |||||
/** | |||||
* Returns the last path element of a path string | |||||
* | |||||
* @param path | |||||
* @return the last element in the path | |||||
*/ | |||||
public static String getLastPathElement(String path) { | |||||
if (path.indexOf('/') > -1) { | |||||
return path.substring(path.lastIndexOf('/') + 1); | |||||
} | |||||
return path; | |||||
} | |||||
} | } |
import com.gitblit.wicket.pages.CommitPage; | import com.gitblit.wicket.pages.CommitPage; | ||||
import com.gitblit.wicket.pages.DocsPage; | import com.gitblit.wicket.pages.DocsPage; | ||||
import com.gitblit.wicket.pages.FederationRegistrationPage; | import com.gitblit.wicket.pages.FederationRegistrationPage; | ||||
import com.gitblit.wicket.pages.ForksPage; | |||||
import com.gitblit.wicket.pages.GitSearchPage; | import com.gitblit.wicket.pages.GitSearchPage; | ||||
import com.gitblit.wicket.pages.GravatarProfilePage; | import com.gitblit.wicket.pages.GravatarProfilePage; | ||||
import com.gitblit.wicket.pages.HistoryPage; | import com.gitblit.wicket.pages.HistoryPage; | ||||
import com.gitblit.wicket.pages.TicketPage; | import com.gitblit.wicket.pages.TicketPage; | ||||
import com.gitblit.wicket.pages.TicketsPage; | import com.gitblit.wicket.pages.TicketsPage; | ||||
import com.gitblit.wicket.pages.TreePage; | import com.gitblit.wicket.pages.TreePage; | ||||
import com.gitblit.wicket.pages.UserPage; | |||||
import com.gitblit.wicket.pages.UsersPage; | import com.gitblit.wicket.pages.UsersPage; | ||||
public class GitBlitWebApp extends WebApplication { | public class GitBlitWebApp extends WebApplication { | ||||
mount("/lucene", LuceneSearchPage.class); | mount("/lucene", LuceneSearchPage.class); | ||||
mount("/project", ProjectPage.class, "p"); | mount("/project", ProjectPage.class, "p"); | ||||
mount("/projects", ProjectsPage.class); | mount("/projects", ProjectsPage.class); | ||||
mount("/user", UserPage.class, "user"); | |||||
mount("/forks", ForksPage.class, "r"); | |||||
} | } | ||||
private void mount(String location, Class<? extends WebPage> clazz, String... parameters) { | private void mount(String location, Class<? extends WebPage> clazz, String... parameters) { |
gb.projects = projects | gb.projects = projects | ||||
gb.project = project | gb.project = project | ||||
gb.allProjects = all projects | gb.allProjects = all projects | ||||
gb.copyToClipboard = copy to clipboard | |||||
gb.copyToClipboard = copy to clipboard | |||||
gb.fork = fork | |||||
gb.forks = forks | |||||
gb.forkRepository = fork {0}? | |||||
gb.repositoryForked = {0} has been forked | |||||
gb.repositoryForkFailed= failed to fork {1} | |||||
gb.personalRepositories = personal repositories | |||||
gb.allowForks = allow forks | |||||
gb.allowForksDescription = allow authorized users to fork this repository | |||||
gb.forkedFrom = forked from | |||||
gb.canFork = can fork | |||||
gb.canForkDescription = user is permitted to fork authorized repositories | |||||
gb.myFork = view my fork | |||||
gb.forksProhibited = forks prohibited | |||||
gb.forksProhibitedWarning = this repository forbids forks |
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Calendar; | import java.util.Calendar; | ||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.Comparator; | |||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.HashSet; | import java.util.HashSet; | ||||
import java.util.LinkedHashMap; | import java.util.LinkedHashMap; | ||||
import org.apache.wicket.MarkupContainer; | import org.apache.wicket.MarkupContainer; | ||||
import org.apache.wicket.PageParameters; | import org.apache.wicket.PageParameters; | ||||
import org.apache.wicket.RedirectToUrlException; | import org.apache.wicket.RedirectToUrlException; | ||||
import org.apache.wicket.RequestCycle; | |||||
import org.apache.wicket.RestartResponseException; | import org.apache.wicket.RestartResponseException; | ||||
import org.apache.wicket.markup.html.CSSPackageResource; | import org.apache.wicket.markup.html.CSSPackageResource; | ||||
import org.apache.wicket.markup.html.WebPage; | import org.apache.wicket.markup.html.WebPage; | ||||
import com.gitblit.utils.StringUtils; | import com.gitblit.utils.StringUtils; | ||||
import com.gitblit.utils.TimeUtils; | import com.gitblit.utils.TimeUtils; | ||||
import com.gitblit.wicket.GitBlitWebSession; | import com.gitblit.wicket.GitBlitWebSession; | ||||
import com.gitblit.wicket.PageRegistration.DropDownMenuItem; | |||||
import com.gitblit.wicket.WicketUtils; | import com.gitblit.wicket.WicketUtils; | ||||
import com.gitblit.wicket.panels.LinkPanel; | import com.gitblit.wicket.panels.LinkPanel; | ||||
return req.getServerName(); | return req.getServerName(); | ||||
} | } | ||||
protected String getRepositoryUrl(RepositoryModel repository) { | |||||
public static String getRepositoryUrl(RepositoryModel repository) { | |||||
StringBuilder sb = new StringBuilder(); | StringBuilder sb = new StringBuilder(); | ||||
sb.append(WicketUtils.getGitblitURL(getRequestCycle().getRequest())); | |||||
sb.append(WicketUtils.getGitblitURL(RequestCycle.get().getRequest())); | |||||
sb.append(Constants.GIT_PATH); | sb.append(Constants.GIT_PATH); | ||||
sb.append(repository.name); | sb.append(repository.name); | ||||
protected List<ProjectModel> getProjectModels() { | protected List<ProjectModel> getProjectModels() { | ||||
final UserModel user = GitBlitWebSession.get().getUser(); | final UserModel user = GitBlitWebSession.get().getUser(); | ||||
List<ProjectModel> projects = GitBlit.self().getProjectModels(user); | |||||
List<ProjectModel> projects = GitBlit.self().getProjectModels(user, true); | |||||
return projects; | return projects; | ||||
} | } | ||||
</wicket:container> | </wicket:container> | ||||
</td></tr> | </td></tr> | ||||
<tr><th colspan="2"><hr/></th></tr> | <tr><th colspan="2"><hr/></th></tr> | ||||
<tr><th><wicket:message key="gb.allowForks"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="allowForks" tabindex="17" /> <span class="help-inline"><wicket:message key="gb.allowForksDescription"></wicket:message></span></label></td></tr> | |||||
<tr><th colspan="2"><hr/></th></tr> | |||||
<tr><th style="vertical-align: top;"><wicket:message key="gb.permittedUsers"></wicket:message></th><td style="padding:2px;"><span wicket:id="users"></span></td></tr> | <tr><th style="vertical-align: top;"><wicket:message key="gb.permittedUsers"></wicket:message></th><td style="padding:2px;"><span wicket:id="users"></span></td></tr> | ||||
<tr><th style="vertical-align: top;"><wicket:message key="gb.permittedTeams"></wicket:message></th><td style="padding:2px;"><span wicket:id="teams"></span></td></tr> | <tr><th style="vertical-align: top;"><wicket:message key="gb.permittedTeams"></wicket:message></th><td style="padding:2px;"><span wicket:id="teams"></span></td></tr> | ||||
<tr><td colspan="2"><h3><wicket:message key="gb.federation"></wicket:message> <small><wicket:message key="gb.federationRepositoryDescription"></wicket:message></small></h3></td></tr> | <tr><td colspan="2"><h3><wicket:message key="gb.federation"></wicket:message> <small><wicket:message key="gb.federationRepositoryDescription"></wicket:message></small></h3></td></tr> | ||||
<tr><th><wicket:message key="gb.federationStrategy"></wicket:message></th><td class="edit"><select class="span4" wicket:id="federationStrategy" tabindex="17" /></td></tr> | |||||
<tr><th><wicket:message key="gb.federationStrategy"></wicket:message></th><td class="edit"><select class="span4" wicket:id="federationStrategy" tabindex="18" /></td></tr> | |||||
<tr><th style="vertical-align: top;"><wicket:message key="gb.federationSets"></wicket:message></th><td style="padding:2px;"><span wicket:id="federationSets"></span></td></tr> | <tr><th style="vertical-align: top;"><wicket:message key="gb.federationSets"></wicket:message></th><td style="padding:2px;"><span wicket:id="federationSets"></span></td></tr> | ||||
<tr><td colspan="2"><h3><wicket:message key="gb.search"></wicket:message> <small><wicket:message key="gb.indexedBranchesDescription"></wicket:message></small></h3></td></tr> | <tr><td colspan="2"><h3><wicket:message key="gb.search"></wicket:message> <small><wicket:message key="gb.indexedBranchesDescription"></wicket:message></small></h3></td></tr> | ||||
<tr><th style="vertical-align: top;"><wicket:message key="gb.indexedBranches"></wicket:message></th><td style="padding:2px;"><span wicket:id="indexedBranches"></span></td></tr> | <tr><th style="vertical-align: top;"><wicket:message key="gb.indexedBranches"></wicket:message></th><td style="padding:2px;"><span wicket:id="indexedBranches"></span></td></tr> |
form.add(new TextField<String>("description")); | form.add(new TextField<String>("description")); | ||||
form.add(new DropDownChoice<String>("owner", GitBlit.self().getAllUsernames()) | form.add(new DropDownChoice<String>("owner", GitBlit.self().getAllUsernames()) | ||||
.setEnabled(GitBlitWebSession.get().canAdmin())); | .setEnabled(GitBlitWebSession.get().canAdmin())); | ||||
form.add(new CheckBox("allowForks")); | |||||
form.add(new DropDownChoice<AccessRestrictionType>("accessRestriction", Arrays | form.add(new DropDownChoice<AccessRestrictionType>("accessRestriction", Arrays | ||||
.asList(AccessRestrictionType.values()), new AccessRestrictionRenderer())); | .asList(AccessRestrictionType.values()), new AccessRestrictionRenderer())); | ||||
form.add(new CheckBox("isFrozen")); | form.add(new CheckBox("isFrozen")); |
<tr><th><wicket:message key="gb.displayName"></wicket:message></th><td class="edit"><input type="text" wicket:id="displayName" size="30" tabindex="4" /></td></tr> | <tr><th><wicket:message key="gb.displayName"></wicket:message></th><td class="edit"><input type="text" wicket:id="displayName" size="30" tabindex="4" /></td></tr> | ||||
<tr><th><wicket:message key="gb.emailAddress"></wicket:message></th><td class="edit"><input type="text" wicket:id="emailAddress" size="30" tabindex="5" /></td></tr> | <tr><th><wicket:message key="gb.emailAddress"></wicket:message></th><td class="edit"><input type="text" wicket:id="emailAddress" size="30" tabindex="5" /></td></tr> | ||||
<tr><th><wicket:message key="gb.canAdmin"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="canAdmin" tabindex="6" /> <span class="help-inline"><wicket:message key="gb.canAdminDescription"></wicket:message></span></label></td></tr> | <tr><th><wicket:message key="gb.canAdmin"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="canAdmin" tabindex="6" /> <span class="help-inline"><wicket:message key="gb.canAdminDescription"></wicket:message></span></label></td></tr> | ||||
<tr><th><wicket:message key="gb.excludeFromFederation"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="excludeFromFederation" tabindex="7" /> <span class="help-inline"><wicket:message key="gb.excludeFromFederationDescription"></wicket:message></span></label></td></tr> | |||||
<tr><th><wicket:message key="gb.canFork"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="canFork" tabindex="7" /> <span class="help-inline"><wicket:message key="gb.canForkDescription"></wicket:message></span></label></td></tr> | |||||
<tr><th><wicket:message key="gb.excludeFromFederation"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="excludeFromFederation" tabindex="8" /> <span class="help-inline"><wicket:message key="gb.excludeFromFederationDescription"></wicket:message></span></label></td></tr> | |||||
<tr><td colspan="2" style="padding-top:15px;"><h3><wicket:message key="gb.accessPermissions"></wicket:message> <small><wicket:message key="gb.accessPermissionsForUserDescription"></wicket:message></small></h3></td></tr> | <tr><td colspan="2" style="padding-top:15px;"><h3><wicket:message key="gb.accessPermissions"></wicket:message> <small><wicket:message key="gb.accessPermissionsForUserDescription"></wicket:message></small></h3></td></tr> | ||||
<tr><th style="vertical-align: top;"><wicket:message key="gb.teamMemberships"></wicket:message></th><td style="padding:2px;"><span wicket:id="teams"></span></td></tr> | <tr><th style="vertical-align: top;"><wicket:message key="gb.teamMemberships"></wicket:message></th><td style="padding:2px;"><span wicket:id="teams"></span></td></tr> | ||||
<tr><td colspan="2"><hr></hr></td></tr> | <tr><td colspan="2"><hr></hr></td></tr> | ||||
<tr><th style="vertical-align: top;"><wicket:message key="gb.restrictedRepositories"></wicket:message></th><td style="padding:2px;"><span wicket:id="repositories"></span></td></tr> | <tr><th style="vertical-align: top;"><wicket:message key="gb.restrictedRepositories"></wicket:message></th><td style="padding:2px;"><span wicket:id="repositories"></span></td></tr> | ||||
<tr><td colspan='2'><div class="form-actions"><input class="btn btn-primary" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" tabindex="8" /> <input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" tabindex="9" /></div></td></tr> | |||||
<tr><td colspan='2'><div class="form-actions"><input class="btn btn-primary" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" tabindex="9" /> <input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" tabindex="10" /></div></td></tr> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
</form> | </form> |
form.add(new TextField<String>("displayName").setEnabled(editDisplayName)); | form.add(new TextField<String>("displayName").setEnabled(editDisplayName)); | ||||
form.add(new TextField<String>("emailAddress").setEnabled(editEmailAddress)); | form.add(new TextField<String>("emailAddress").setEnabled(editEmailAddress)); | ||||
form.add(new CheckBox("canAdmin")); | form.add(new CheckBox("canAdmin")); | ||||
form.add(new CheckBox("canFork")); | |||||
form.add(new CheckBox("excludeFromFederation")); | form.add(new CheckBox("excludeFromFederation")); | ||||
form.add(repositories); | form.add(repositories); | ||||
form.add(teams.setEnabled(editTeams)); | form.add(teams.setEnabled(editTeams)); |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" | |||||
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" | |||||
xml:lang="en" | |||||
lang="en"> | |||||
<body> | |||||
<wicket:extend> | |||||
<div class="forkSource"> | |||||
<b><span class="repositorySwatch" wicket:id="forkSourceSwatch"></span></b> | |||||
<span wicket:id="forkSourceAvatar" style="vertical-align: baseline;"></span> | |||||
<span wicket:id="forkSourceProject">[a project]</span> / <span wicket:id="forkSource">[a fork]</span> | |||||
</div> | |||||
<div wicket:id="fork"> | |||||
<div class="forkEntry"> | |||||
<span wicket:id="anAvatar" style="vertical-align: baseline;"></span> | |||||
<span wicket:id="aProject">[a project]</span> / <span wicket:id="aFork">[a fork]</span> | |||||
</div> | |||||
</div> | |||||
</wicket:extend> | |||||
</body> | |||||
</html> |
/* | |||||
* Copyright 2012 gitblit.com. | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
*/ | |||||
package com.gitblit.wicket.pages; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import org.apache.wicket.Component; | |||||
import org.apache.wicket.PageParameters; | |||||
import org.apache.wicket.markup.html.basic.Label; | |||||
import org.apache.wicket.markup.repeater.Item; | |||||
import org.apache.wicket.markup.repeater.data.DataView; | |||||
import org.apache.wicket.markup.repeater.data.ListDataProvider; | |||||
import org.eclipse.jgit.lib.PersonIdent; | |||||
import com.gitblit.GitBlit; | |||||
import com.gitblit.Keys; | |||||
import com.gitblit.models.RepositoryModel; | |||||
import com.gitblit.models.UserModel; | |||||
import com.gitblit.utils.ArrayUtils; | |||||
import com.gitblit.utils.StringUtils; | |||||
import com.gitblit.wicket.GitBlitWebSession; | |||||
import com.gitblit.wicket.WicketUtils; | |||||
import com.gitblit.wicket.panels.GravatarImage; | |||||
import com.gitblit.wicket.panels.LinkPanel; | |||||
public class ForksPage extends RepositoryPage { | |||||
public ForksPage(PageParameters params) { | |||||
super(params); | |||||
RepositoryModel model = getRepositoryModel(); | |||||
RepositoryModel origin; | |||||
List<String> list; | |||||
if (ArrayUtils.isEmpty(model.forks)) { | |||||
// origin repository has forks | |||||
origin = GitBlit.self().getRepositoryModel(model.originRepository); | |||||
list = new ArrayList<String>(origin.forks); | |||||
} else { | |||||
// this repository has forks | |||||
origin = model; | |||||
list = new ArrayList<String>(model.forks); | |||||
} | |||||
if (origin.isPersonalRepository()) { | |||||
// personal repository | |||||
UserModel user = GitBlit.self().getUserModel(origin.projectPath.substring(1)); | |||||
PersonIdent ident = new PersonIdent(user.getDisplayName(), user.emailAddress); | |||||
add(new GravatarImage("forkSourceAvatar", ident, 20)); | |||||
add(new Label("forkSourceSwatch").setVisible(false)); | |||||
add(new LinkPanel("forkSourceProject", null, user.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(user.username))); | |||||
} else { | |||||
// standard repository | |||||
add(new GravatarImage("forkSourceAvatar", new PersonIdent("", ""), 20).setVisible(false)); | |||||
Component swatch; | |||||
if (origin.isBare){ | |||||
swatch = new Label("forkSourceSwatch", " ").setEscapeModelStrings(false); | |||||
} else { | |||||
swatch = new Label("forkSourceSwatch", "!"); | |||||
WicketUtils.setHtmlTooltip(swatch, getString("gb.workingCopyWarning")); | |||||
} | |||||
WicketUtils.setCssBackground(swatch, origin.toString()); | |||||
add(swatch); | |||||
final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true); | |||||
swatch.setVisible(showSwatch); | |||||
String projectName = origin.projectPath; | |||||
if (StringUtils.isEmpty(projectName)) { | |||||
projectName = GitBlit.getString(Keys.web.repositoryRootGroupName, "main"); | |||||
} | |||||
add(new LinkPanel("forkSourceProject", null, projectName, ProjectPage.class, WicketUtils.newProjectParameter(origin.projectPath))); | |||||
} | |||||
String source = StringUtils.getLastPathElement(origin.name); | |||||
add(new LinkPanel("forkSource", null, StringUtils.stripDotGit(source), SummaryPage.class, WicketUtils.newRepositoryParameter(origin.name))); | |||||
// only display user-accessible forks | |||||
UserModel user = GitBlitWebSession.get().getUser(); | |||||
List<RepositoryModel> forks = new ArrayList<RepositoryModel>(); | |||||
for (String aFork : list) { | |||||
RepositoryModel fork = GitBlit.self().getRepositoryModel(user, aFork); | |||||
if (fork != null) { | |||||
forks.add(fork); | |||||
} | |||||
} | |||||
ListDataProvider<RepositoryModel> forksDp = new ListDataProvider<RepositoryModel>(forks); | |||||
DataView<RepositoryModel> forksList = new DataView<RepositoryModel>("fork", forksDp) { | |||||
private static final long serialVersionUID = 1L; | |||||
public void populateItem(final Item<RepositoryModel> item) { | |||||
RepositoryModel fork = item.getModelObject(); | |||||
if (fork.isPersonalRepository()) { | |||||
UserModel user = GitBlit.self().getUserModel(fork.projectPath.substring(1)); | |||||
PersonIdent ident = new PersonIdent(user.getDisplayName(), user.emailAddress); | |||||
item.add(new GravatarImage("anAvatar", ident, 20)); | |||||
item.add(new LinkPanel("aProject", null, user.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(user.username))); | |||||
} else { | |||||
PersonIdent ident = new PersonIdent(fork.name, fork.name); | |||||
item.add(new GravatarImage("anAvatar", ident, 20)); | |||||
item.add(new LinkPanel("aProject", null, fork.projectPath, ProjectPage.class, WicketUtils.newProjectParameter(fork.projectPath))); | |||||
} | |||||
String repo = StringUtils.getLastPathElement(fork.name); | |||||
item.add(new LinkPanel("aFork", null, StringUtils.stripDotGit(repo), SummaryPage.class, WicketUtils.newRepositoryParameter(fork.name))); | |||||
WicketUtils.setCssStyle(item, "margin-left:25px;"); | |||||
} | |||||
}; | |||||
add(forksList); | |||||
} | |||||
@Override | |||||
protected String getPageName() { | |||||
return getString("gb.forks"); | |||||
} | |||||
} |
int nextPage = pageNumber + 1; | int nextPage = pageNumber + 1; | ||||
SearchPanel search = new SearchPanel("searchPanel", repositoryName, objectId, value, | SearchPanel search = new SearchPanel("searchPanel", repositoryName, objectId, value, | ||||
searchType, getRepository(), -1, pageNumber - 1); | |||||
searchType, getRepository(), -1, pageNumber - 1, getRepositoryModel().showRemoteBranches); | |||||
boolean hasMore = search.hasMore(); | boolean hasMore = search.hasMore(); | ||||
add(search); | add(search); | ||||
int nextPage = pageNumber + 1; | int nextPage = pageNumber + 1; | ||||
HistoryPanel history = new HistoryPanel("historyPanel", repositoryName, objectId, path, | HistoryPanel history = new HistoryPanel("historyPanel", repositoryName, objectId, path, | ||||
getRepository(), -1, pageNumber - 1); | |||||
getRepository(), -1, pageNumber - 1, getRepositoryModel().showRemoteBranches); | |||||
boolean hasMore = history.hasMore(); | boolean hasMore = history.hasMore(); | ||||
add(history); | add(history); | ||||
refid = getRepositoryModel().HEAD; | refid = getRepositoryModel().HEAD; | ||||
} | } | ||||
LogPanel logPanel = new LogPanel("logPanel", repositoryName, refid, getRepository(), -1, | LogPanel logPanel = new LogPanel("logPanel", repositoryName, refid, getRepository(), -1, | ||||
pageNumber - 1); | |||||
pageNumber - 1, getRepositoryModel().showRemoteBranches); | |||||
boolean hasMore = logPanel.hasMore(); | boolean hasMore = logPanel.hasMore(); | ||||
add(logPanel); | add(logPanel); | ||||
<body> | <body> | ||||
<wicket:extend> | <wicket:extend> | ||||
<wicket:fragment wicket:id="repositoryAdminLinks"> | |||||
<span class="link"> | |||||
<a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | |||||
| <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | |||||
| <a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a> | |||||
| <a wicket:id="deleteRepository"><wicket:message key="gb.delete">[delete]</wicket:message></a> | |||||
</span> | |||||
</wicket:fragment> | |||||
<wicket:fragment wicket:id="repositoryOwnerLinks"> | |||||
<span class="link"> | |||||
<a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | |||||
| <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | |||||
| <a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a> | |||||
</span> | |||||
</wicket:fragment> | |||||
<wicket:fragment wicket:id="repositoryUserLinks"> | |||||
<span class="link"> | |||||
<a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | |||||
| <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | |||||
</span> | |||||
</wicket:fragment> | |||||
<div class="row"> | <div class="row"> | ||||
<div class="span12"> | <div class="span12"> | ||||
<div class="markdown" wicket:id="repositoriesMessage">[repositories message]</div> | <div class="markdown" wicket:id="repositoriesMessage">[repositories message]</div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<!-- repositories --> | |||||
<div class="row"> | <div class="row"> | ||||
<div class="span6" style="border-top:1px solid #eee;" wicket:id="repository"> | |||||
<div style="padding-top:15px;padding-bottom:15px;margin-right:15px;"> | |||||
<div class="pull-right" style="text-align:right;padding-right:15px;"> | |||||
<span wicket:id="repositoryLinks"></span> | |||||
<div> | |||||
<img class="inlineIcon" wicket:id="frozenIcon" /> | |||||
<img class="inlineIcon" wicket:id="federatedIcon" /> | |||||
<a style="text-decoration: none;" wicket:id="tickets" wicket:message="title:gb.tickets"> | |||||
<img style="border:0px;vertical-align:middle;" src="bug_16x16.png"></img> | |||||
</a> | |||||
<a style="text-decoration: none;" wicket:id="docs" wicket:message="title:gb.docs"> | |||||
<img style="border:0px;vertical-align:middle;" src="book_16x16.png"></img> | |||||
</a> | |||||
<a style="text-decoration: none;" wicket:id="syndication" wicket:message="title:gb.feed"> | |||||
<img style="border:0px;vertical-align:middle;" src="feed_16x16.png"></img> | |||||
</a> | |||||
</div> | |||||
<span style="color: #999;font-style:italic;font-size:0.8em;" wicket:id="repositoryOwner">[owner]</span> | |||||
</div> | |||||
<h3><span class="repositorySwatch" wicket:id="repositorySwatch"></span> | |||||
<span style="padding-left:3px;" wicket:id="repositoryName">[repository name]</span> | |||||
<img class="inlineIcon" wicket:id="accessRestrictionIcon" /> | |||||
</h3> | |||||
<div style="padding-left:20px;"> | |||||
<div style="padding-bottom:10px" wicket:id="repositoryDescription">[repository description]</div> | |||||
<div style="color: #999;"> | |||||
<wicket:message key="gb.lastChange">[last change]</wicket:message> <span wicket:id="repositoryLastChange">[last change]</span>, | |||||
<span style="font-size:0.8em;" wicket:id="repositorySize">[repository size]</span> | |||||
</div> | |||||
<div class="hidden-phone hidden-tablet" wicket:id="repositoryCloneUrl">[repository clone url]</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="span6" style="border-bottom:1px solid #eee;" wicket:id="repositoryList"> | |||||
<span wicket:id="repository"></span> | |||||
</div> | |||||
</div> | |||||
</div> | </div> | ||||
<!-- activity tab --> | <!-- activity tab --> |
import org.apache.wicket.RedirectException; | import org.apache.wicket.RedirectException; | ||||
import org.apache.wicket.behavior.HeaderContributor; | import org.apache.wicket.behavior.HeaderContributor; | ||||
import org.apache.wicket.markup.html.basic.Label; | import org.apache.wicket.markup.html.basic.Label; | ||||
import org.apache.wicket.markup.html.link.BookmarkablePageLink; | |||||
import org.apache.wicket.markup.html.link.ExternalLink; | import org.apache.wicket.markup.html.link.ExternalLink; | ||||
import org.apache.wicket.markup.html.link.Link; | |||||
import org.apache.wicket.markup.html.panel.Fragment; | |||||
import org.apache.wicket.markup.repeater.Item; | import org.apache.wicket.markup.repeater.Item; | ||||
import org.apache.wicket.markup.repeater.data.DataView; | import org.apache.wicket.markup.repeater.data.DataView; | ||||
import org.apache.wicket.markup.repeater.data.ListDataProvider; | import org.apache.wicket.markup.repeater.data.ListDataProvider; | ||||
import com.gitblit.models.RepositoryModel; | import com.gitblit.models.RepositoryModel; | ||||
import com.gitblit.models.UserModel; | import com.gitblit.models.UserModel; | ||||
import com.gitblit.utils.ActivityUtils; | import com.gitblit.utils.ActivityUtils; | ||||
import com.gitblit.utils.ArrayUtils; | |||||
import com.gitblit.utils.MarkdownUtils; | import com.gitblit.utils.MarkdownUtils; | ||||
import com.gitblit.utils.StringUtils; | import com.gitblit.utils.StringUtils; | ||||
import com.gitblit.wicket.GitBlitWebApp; | import com.gitblit.wicket.GitBlitWebApp; | ||||
import com.gitblit.wicket.charting.GoogleLineChart; | import com.gitblit.wicket.charting.GoogleLineChart; | ||||
import com.gitblit.wicket.charting.GooglePieChart; | import com.gitblit.wicket.charting.GooglePieChart; | ||||
import com.gitblit.wicket.panels.ActivityPanel; | import com.gitblit.wicket.panels.ActivityPanel; | ||||
import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation; | |||||
import com.gitblit.wicket.panels.LinkPanel; | |||||
import com.gitblit.wicket.panels.RepositoryUrlPanel; | |||||
import com.gitblit.wicket.panels.ProjectRepositoryPanel; | |||||
public class ProjectPage extends RootPage { | public class ProjectPage extends RootPage { | ||||
} | } | ||||
}); | }); | ||||
final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true); | |||||
final boolean gitServlet = GitBlit.getBoolean(Keys.git.enableGitServlet, true); | |||||
final boolean showSize = GitBlit.getBoolean(Keys.web.showRepositorySizes, true); | |||||
final ListDataProvider<RepositoryModel> dp = new ListDataProvider<RepositoryModel>(repositories); | final ListDataProvider<RepositoryModel> dp = new ListDataProvider<RepositoryModel>(repositories); | ||||
DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("repository", dp) { | |||||
DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("repositoryList", dp) { | |||||
private static final long serialVersionUID = 1L; | private static final long serialVersionUID = 1L; | ||||
public void populateItem(final Item<RepositoryModel> item) { | public void populateItem(final Item<RepositoryModel> item) { | ||||
final RepositoryModel entry = item.getModelObject(); | final RepositoryModel entry = item.getModelObject(); | ||||
// repository swatch | |||||
Component swatch; | |||||
if (entry.isBare){ | |||||
swatch = new Label("repositorySwatch", " ").setEscapeModelStrings(false); | |||||
} else { | |||||
swatch = new Label("repositorySwatch", "!"); | |||||
WicketUtils.setHtmlTooltip(swatch, getString("gb.workingCopyWarning")); | |||||
} | |||||
WicketUtils.setCssBackground(swatch, entry.toString()); | |||||
item.add(swatch); | |||||
swatch.setVisible(showSwatch); | |||||
PageParameters pp = WicketUtils.newRepositoryParameter(entry.name); | |||||
item.add(new LinkPanel("repositoryName", "list", StringUtils.getRelativePath(projectPath, StringUtils.stripDotGit(entry.name)), SummaryPage.class, pp)); | |||||
item.add(new Label("repositoryDescription", entry.description).setVisible(!StringUtils.isEmpty(entry.description))); | |||||
item.add(new BookmarkablePageLink<Void>("tickets", TicketsPage.class, pp).setVisible(entry.useTickets)); | |||||
item.add(new BookmarkablePageLink<Void>("docs", DocsPage.class, pp).setVisible(entry.useDocs)); | |||||
if (entry.isFrozen) { | |||||
item.add(WicketUtils.newImage("frozenIcon", "cold_16x16.png", | |||||
getString("gb.isFrozen"))); | |||||
} else { | |||||
item.add(WicketUtils.newClearPixel("frozenIcon").setVisible(false)); | |||||
} | |||||
if (entry.isFederated) { | |||||
item.add(WicketUtils.newImage("federatedIcon", "federated_16x16.png", | |||||
getString("gb.isFederated"))); | |||||
} else { | |||||
item.add(WicketUtils.newClearPixel("federatedIcon").setVisible(false)); | |||||
} | |||||
switch (entry.accessRestriction) { | |||||
case NONE: | |||||
item.add(WicketUtils.newBlankImage("accessRestrictionIcon").setVisible(false)); | |||||
break; | |||||
case PUSH: | |||||
item.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png", | |||||
getAccessRestrictions().get(entry.accessRestriction))); | |||||
break; | |||||
case CLONE: | |||||
item.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png", | |||||
getAccessRestrictions().get(entry.accessRestriction))); | |||||
break; | |||||
case VIEW: | |||||
item.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png", | |||||
getAccessRestrictions().get(entry.accessRestriction))); | |||||
break; | |||||
default: | |||||
item.add(WicketUtils.newBlankImage("accessRestrictionIcon")); | |||||
} | |||||
item.add(new Label("repositoryOwner", StringUtils.isEmpty(entry.owner) ? "" : (entry.owner + " (" + getString("gb.owner") + ")"))); | |||||
UserModel user = GitBlitWebSession.get().getUser(); | |||||
Fragment repositoryLinks; | |||||
boolean showOwner = user != null && user.username.equalsIgnoreCase(entry.owner); | |||||
if (showAdmin || showOwner) { | |||||
repositoryLinks = new Fragment("repositoryLinks", | |||||
showAdmin ? "repositoryAdminLinks" : "repositoryOwnerLinks", this); | |||||
repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", | |||||
EditRepositoryPage.class, WicketUtils | |||||
.newRepositoryParameter(entry.name))); | |||||
if (showAdmin) { | |||||
Link<Void> deleteLink = new Link<Void>("deleteRepository") { | |||||
private static final long serialVersionUID = 1L; | |||||
@Override | |||||
public void onClick() { | |||||
if (GitBlit.self().deleteRepositoryModel(entry)) { | |||||
info(MessageFormat.format(getString("gb.repositoryDeleted"), entry)); | |||||
// TODO dp.remove(entry); | |||||
} else { | |||||
error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), entry)); | |||||
} | |||||
} | |||||
}; | |||||
deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( | |||||
getString("gb.deleteRepository"), entry))); | |||||
repositoryLinks.add(deleteLink); | |||||
} | |||||
} else { | |||||
repositoryLinks = new Fragment("repositoryLinks", "repositoryUserLinks", this); | |||||
} | |||||
repositoryLinks.add(new BookmarkablePageLink<Void>("tree", TreePage.class, | |||||
WicketUtils.newRepositoryParameter(entry.name)).setEnabled(entry.hasCommits)); | |||||
repositoryLinks.add(new BookmarkablePageLink<Void>("log", LogPage.class, | |||||
WicketUtils.newRepositoryParameter(entry.name)).setEnabled(entry.hasCommits)); | |||||
item.add(repositoryLinks); | |||||
String lastChange; | |||||
if (entry.lastChange.getTime() == 0) { | |||||
lastChange = "--"; | |||||
} else { | |||||
lastChange = getTimeUtils().timeAgo(entry.lastChange); | |||||
} | |||||
Label lastChangeLabel = new Label("repositoryLastChange", lastChange); | |||||
item.add(lastChangeLabel); | |||||
WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange)); | |||||
if (entry.hasCommits) { | |||||
// Existing repository | |||||
item.add(new Label("repositorySize", entry.size).setVisible(showSize)); | |||||
} else { | |||||
// New repository | |||||
item.add(new Label("repositorySize", getString("gb.empty")) | |||||
.setEscapeModelStrings(false)); | |||||
} | |||||
item.add(new ExternalLink("syndication", SyndicationServlet.asLink("", | |||||
entry.name, null, 0))); | |||||
List<String> repositoryUrls = new ArrayList<String>(); | |||||
if (gitServlet) { | |||||
// add the Gitblit repository url | |||||
repositoryUrls.add(getRepositoryUrl(entry)); | |||||
} | |||||
repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(entry.name)); | |||||
String primaryUrl = ArrayUtils.isEmpty(repositoryUrls) ? "" : repositoryUrls.remove(0); | |||||
item.add(new RepositoryUrlPanel("repositoryCloneUrl", primaryUrl)); | |||||
ProjectRepositoryPanel row = new ProjectRepositoryPanel("repository", | |||||
getLocalizer(), this, showAdmin, entry, getAccessRestrictions()); | |||||
item.add(row); | |||||
} | } | ||||
}; | }; | ||||
add(dataView); | add(dataView); | ||||
protected List<ProjectModel> getProjectModels() { | protected List<ProjectModel> getProjectModels() { | ||||
if (projectModels.isEmpty()) { | if (projectModels.isEmpty()) { | ||||
final UserModel user = GitBlitWebSession.get().getUser(); | final UserModel user = GitBlitWebSession.get().getUser(); | ||||
List<ProjectModel> projects = GitBlit.self().getProjectModels(user); | |||||
List<ProjectModel> projects = GitBlit.self().getProjectModels(user, false); | |||||
projectModels.addAll(projects); | projectModels.addAll(projects); | ||||
} | } | ||||
return projectModels; | return projectModels; | ||||
protected List<DropDownMenuItem> getProjectsMenu() { | protected List<DropDownMenuItem> getProjectsMenu() { | ||||
List<DropDownMenuItem> menu = new ArrayList<DropDownMenuItem>(); | List<DropDownMenuItem> menu = new ArrayList<DropDownMenuItem>(); | ||||
List<ProjectModel> projects = getProjectModels(); | |||||
List<ProjectModel> projects = new ArrayList<ProjectModel>(); | |||||
for (ProjectModel model : getProjectModels()) { | |||||
if (!model.isUserProject()) { | |||||
projects.add(model); | |||||
} | |||||
} | |||||
int maxProjects = 15; | int maxProjects = 15; | ||||
boolean showAllProjects = projects.size() > maxProjects; | boolean showAllProjects = projects.size() > maxProjects; | ||||
if (showAllProjects) { | if (showAllProjects) { |
import com.gitblit.GitBlit; | import com.gitblit.GitBlit; | ||||
import com.gitblit.Keys; | import com.gitblit.Keys; | ||||
import com.gitblit.models.ProjectModel; | import com.gitblit.models.ProjectModel; | ||||
import com.gitblit.models.UserModel; | |||||
import com.gitblit.utils.MarkdownUtils; | import com.gitblit.utils.MarkdownUtils; | ||||
import com.gitblit.utils.StringUtils; | import com.gitblit.utils.StringUtils; | ||||
import com.gitblit.wicket.GitBlitWebSession; | import com.gitblit.wicket.GitBlitWebSession; | ||||
protected boolean reusePageParameters() { | protected boolean reusePageParameters() { | ||||
return true; | return true; | ||||
} | } | ||||
@Override | |||||
protected List<ProjectModel> getProjectModels() { | |||||
final UserModel user = GitBlitWebSession.get().getUser(); | |||||
List<ProjectModel> projects = GitBlit.self().getProjectModels(user, false); | |||||
return projects; | |||||
} | |||||
private void setup(PageParameters params) { | private void setup(PageParameters params) { | ||||
setupPage("", ""); | setupPage("", ""); |
<!-- page header --> | <!-- page header --> | ||||
<div class="pageTitle"> | <div class="pageTitle"> | ||||
<div class="row"> | <div class="row"> | ||||
<div wicket:id="workingCopy"></div> | |||||
<div class="span9"> | |||||
<h2><span wicket:id="repositoryName">[repository name]</span> <small><span wicket:id="pageName">[page name]</span></small></h2> | |||||
<div class="controls"> | |||||
<span wicket:id="workingCopyIndicator"></span> | |||||
<span wicket:id="forksProhibitedIndicator"></span> | |||||
<div class="hidden-phone btn-group pull-right"> | |||||
<!-- future spot for other repo buttons --> | |||||
<a class="btn" wicket:id="myForkLink"><i class="icon-random"></i> <wicket:message key="gb.myFork"></wicket:message></a> | |||||
<a class="btn" wicket:id="forkLink"><i class="icon-random"></i> <wicket:message key="gb.fork"></wicket:message></a> | |||||
</div> | |||||
</div> | |||||
<div class="span7"> | |||||
<div><span class="project" wicket:id="projectTitle">[project title]</span>/<span class="repository" wicket:id="repositoryName">[repository name]</span> <span wicket:id="pageName">[page name]</span></div> | |||||
<span wicket:id="originRepository">[origin repository]</span> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<wicket:child /> | <wicket:child /> | ||||
</div> | </div> | ||||
<wicket:fragment wicket:id="originFragment"> | |||||
<p class="originRepository"><wicket:message key="gb.forkedFrom">[forked from]</wicket:message> <span wicket:id="originRepository">[origin repository]</span></p> | |||||
</wicket:fragment> | |||||
<wicket:fragment wicket:id="workingCopyFragment"> | <wicket:fragment wicket:id="workingCopyFragment"> | ||||
<p class="pull-right" style="padding-top:5px;"> | |||||
<span class="alert alert-info" style="padding: 8px 14px 8px 14px;vertical-align: middle;"><i class="icon-exclamation-sign" style="vertical-align: middle;"></i> <span class="hidden-phone" wicket:id="workingCopy" style="font-weight:bold;">[working copy]</span></span> | |||||
</p> | |||||
<div class="pull-right" style="padding-top:0px;margin-bottom:0px;padding-left:5px"> | |||||
<span class="alert alert-info" style="padding: 6px 14px 6px 14px;vertical-align: middle;"><i class="icon-exclamation-sign"></i> <span class="hidden-phone" wicket:id="workingCopy" style="font-weight:bold;">[working copy]</span></span> | |||||
</div> | |||||
</wicket:fragment> | </wicket:fragment> | ||||
<wicket:fragment wicket:id="forksProhibitedFragment"> | |||||
<div class="pull-right" style="padding-top:0px;margin-bottom:0px;padding-left:5px"> | |||||
<span class="alert alert-error" style="padding: 6px 14px 6px 14px;vertical-align: middle;"><i class="icon-ban-circle"></i> <span class="hidden-phone" wicket:id="forksProhibited" style="font-weight:bold;">[forks prohibited]</span></span> | |||||
</div> | |||||
</wicket:fragment> | |||||
</wicket:extend> | </wicket:extend> | ||||
</body> | </body> | ||||
</html> | </html> |
import org.apache.wicket.Component; | import org.apache.wicket.Component; | ||||
import org.apache.wicket.PageParameters; | import org.apache.wicket.PageParameters; | ||||
import org.apache.wicket.RedirectException; | |||||
import org.apache.wicket.markup.html.basic.Label; | import org.apache.wicket.markup.html.basic.Label; | ||||
import org.apache.wicket.markup.html.form.DropDownChoice; | import org.apache.wicket.markup.html.form.DropDownChoice; | ||||
import org.apache.wicket.markup.html.form.TextField; | import org.apache.wicket.markup.html.form.TextField; | ||||
import org.apache.wicket.markup.html.link.ExternalLink; | import org.apache.wicket.markup.html.link.ExternalLink; | ||||
import org.apache.wicket.markup.html.link.Link; | |||||
import org.apache.wicket.markup.html.panel.Fragment; | import org.apache.wicket.markup.html.panel.Fragment; | ||||
import org.apache.wicket.model.IModel; | import org.apache.wicket.model.IModel; | ||||
import org.apache.wicket.model.Model; | import org.apache.wicket.model.Model; | ||||
import com.gitblit.Keys; | import com.gitblit.Keys; | ||||
import com.gitblit.PagesServlet; | import com.gitblit.PagesServlet; | ||||
import com.gitblit.SyndicationServlet; | import com.gitblit.SyndicationServlet; | ||||
import com.gitblit.models.ProjectModel; | |||||
import com.gitblit.models.RepositoryModel; | import com.gitblit.models.RepositoryModel; | ||||
import com.gitblit.models.SubmoduleModel; | import com.gitblit.models.SubmoduleModel; | ||||
import com.gitblit.models.UserModel; | |||||
import com.gitblit.utils.ArrayUtils; | import com.gitblit.utils.ArrayUtils; | ||||
import com.gitblit.utils.JGitUtils; | import com.gitblit.utils.JGitUtils; | ||||
import com.gitblit.utils.StringUtils; | import com.gitblit.utils.StringUtils; | ||||
import com.gitblit.wicket.PageRegistration.OtherPageLink; | import com.gitblit.wicket.PageRegistration.OtherPageLink; | ||||
import com.gitblit.wicket.SessionlessForm; | import com.gitblit.wicket.SessionlessForm; | ||||
import com.gitblit.wicket.WicketUtils; | import com.gitblit.wicket.WicketUtils; | ||||
import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation; | |||||
import com.gitblit.wicket.panels.LinkPanel; | import com.gitblit.wicket.panels.LinkPanel; | ||||
import com.gitblit.wicket.panels.NavigationPanel; | import com.gitblit.wicket.panels.NavigationPanel; | ||||
import com.gitblit.wicket.panels.RefsPanel; | import com.gitblit.wicket.panels.RefsPanel; | ||||
public RepositoryPage(PageParameters params) { | public RepositoryPage(PageParameters params) { | ||||
super(params); | super(params); | ||||
repositoryName = WicketUtils.getRepositoryName(params); | repositoryName = WicketUtils.getRepositoryName(params); | ||||
if (repositoryName.indexOf('/') > -1) { | |||||
projectName = repositoryName.substring(0, repositoryName.indexOf('/')); | |||||
} else { | |||||
String root =StringUtils.getFirstPathElement(repositoryName); | |||||
if (StringUtils.isEmpty(root)) { | |||||
projectName = GitBlit.getString(Keys.web.repositoryRootGroupName, "main"); | projectName = GitBlit.getString(Keys.web.repositoryRootGroupName, "main"); | ||||
} else { | |||||
projectName = root; | |||||
} | } | ||||
objectId = WicketUtils.getObject(params); | objectId = WicketUtils.getObject(params); | ||||
// standard links | // standard links | ||||
pages.put("repositories", new PageRegistration("gb.repositories", RepositoriesPage.class)); | pages.put("repositories", new PageRegistration("gb.repositories", RepositoriesPage.class)); | ||||
pages.put("project", new PageRegistration("gb.project", ProjectPage.class, WicketUtils.newProjectParameter(projectName))); | |||||
pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params)); | pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params)); | ||||
pages.put("log", new PageRegistration("gb.log", LogPage.class, params)); | pages.put("log", new PageRegistration("gb.log", LogPage.class, params)); | ||||
pages.put("branches", new PageRegistration("gb.branches", BranchesPage.class, params)); | pages.put("branches", new PageRegistration("gb.branches", BranchesPage.class, params)); | ||||
Repository r = getRepository(); | Repository r = getRepository(); | ||||
RepositoryModel model = getRepositoryModel(); | RepositoryModel model = getRepositoryModel(); | ||||
// forks list button | |||||
if (StringUtils.isEmpty(model.originRepository)) { | |||||
if (!ArrayUtils.isEmpty(model.forks)) { | |||||
// this origin repository has forks | |||||
pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params)); | |||||
} | |||||
} else { | |||||
// this is a fork of another repository | |||||
pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params)); | |||||
} | |||||
// per-repository extra page links | // per-repository extra page links | ||||
if (model.useTickets && TicgitUtils.getTicketsBranch(r) != null) { | if (model.useTickets && TicgitUtils.getTicketsBranch(r) != null) { | ||||
pages.put("tickets", new PageRegistration("gb.tickets", TicketsPage.class, params)); | pages.put("tickets", new PageRegistration("gb.tickets", TicketsPage.class, params)); | ||||
@Override | @Override | ||||
protected void setupPage(String repositoryName, String pageName) { | protected void setupPage(String repositoryName, String pageName) { | ||||
add(new LinkPanel("repositoryName", null, StringUtils.stripDotGit(repositoryName), | |||||
SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryName))); | |||||
String projectName = StringUtils.getFirstPathElement(repositoryName); | |||||
ProjectModel project = GitBlit.self().getProjectModel(projectName); | |||||
if (project.isUserProject()) { | |||||
// user-as-project | |||||
add(new LinkPanel("projectTitle", null, project.getDisplayName(), | |||||
UserPage.class, WicketUtils.newUsernameParameter(project.name.substring(1)))); | |||||
} else { | |||||
// project | |||||
add(new LinkPanel("projectTitle", null, project.name, | |||||
ProjectPage.class, WicketUtils.newProjectParameter(project.name))); | |||||
} | |||||
String name = StringUtils.stripDotGit(repositoryName); | |||||
if (!StringUtils.isEmpty(projectName) && name.startsWith(projectName)) { | |||||
name = name.substring(projectName.length() + 1); | |||||
} | |||||
add(new LinkPanel("repositoryName", null, name, SummaryPage.class, | |||||
WicketUtils.newRepositoryParameter(repositoryName))); | |||||
add(new Label("pageName", pageName).setRenderBodyOnly(true)); | add(new Label("pageName", pageName).setRenderBodyOnly(true)); | ||||
// indicate origin repository | |||||
RepositoryModel model = getRepositoryModel(); | |||||
if (StringUtils.isEmpty(model.originRepository)) { | |||||
add(new Label("originRepository").setVisible(false)); | |||||
} else { | |||||
Fragment forkFrag = new Fragment("originRepository", "originFragment", this); | |||||
forkFrag.add(new LinkPanel("originRepository", null, StringUtils.stripDotGit(model.originRepository), | |||||
SummaryPage.class, WicketUtils.newRepositoryParameter(model.originRepository))); | |||||
add(forkFrag); | |||||
} | |||||
if (getRepositoryModel().isBare) { | if (getRepositoryModel().isBare) { | ||||
add(new Label("workingCopy").setVisible(false)); | |||||
add(new Label("workingCopyIndicator").setVisible(false)); | |||||
} else { | } else { | ||||
Fragment fragment = new Fragment("workingCopy", "workingCopyFragment", this); | |||||
Fragment wc = new Fragment("workingCopyIndicator", "workingCopyFragment", this); | |||||
Label lbl = new Label("workingCopy", getString("gb.workingCopy")); | Label lbl = new Label("workingCopy", getString("gb.workingCopy")); | ||||
WicketUtils.setHtmlTooltip(lbl, getString("gb.workingCopyWarning")); | WicketUtils.setHtmlTooltip(lbl, getString("gb.workingCopyWarning")); | ||||
fragment.add(lbl); | |||||
add(fragment); | |||||
wc.add(lbl); | |||||
add(wc); | |||||
} | } | ||||
if (getRepositoryModel().allowForks) { | |||||
add(new Label("forksProhibitedIndicator").setVisible(false)); | |||||
} else { | |||||
Fragment wc = new Fragment("forksProhibitedIndicator", "forksProhibitedFragment", this); | |||||
Label lbl = new Label("forksProhibited", getString("gb.forksProhibited")); | |||||
WicketUtils.setHtmlTooltip(lbl, getString("gb.forksProhibitedWarning")); | |||||
wc.add(lbl); | |||||
add(wc); | |||||
} | |||||
UserModel user = GitBlitWebSession.get().getUser(); | |||||
// fork button | |||||
if (user != null) { | |||||
final String clonedRepo = MessageFormat.format("~{0}/{1}.git", user.username, StringUtils.stripDotGit(StringUtils.getLastPathElement(model.name))); | |||||
boolean hasClone = GitBlit.self().hasRepository(clonedRepo) && !getRepositoryModel().name.equals(clonedRepo); | |||||
if (user.canForkRepository(model) && !hasClone) { | |||||
Link<Void> forkLink = new Link<Void>("forkLink") { | |||||
private static final long serialVersionUID = 1L; | |||||
@Override | |||||
public void onClick() { | |||||
RepositoryModel model = getRepositoryModel(); | |||||
if (GitBlit.self().fork(model, GitBlitWebSession.get().getUser())) { | |||||
throw new RedirectException(SummaryPage.class, WicketUtils.newRepositoryParameter(clonedRepo)); | |||||
} else { | |||||
error(MessageFormat.format(getString("gb.repositoryForkFailed"), model)); | |||||
} | |||||
} | |||||
}; | |||||
forkLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( | |||||
getString("gb.forkRepository"), getRepositoryModel()))); | |||||
add(forkLink); | |||||
} else { | |||||
// user not allowed to fork or fork already exists or repo forbids forking | |||||
add(new ExternalLink("forkLink", "").setVisible(false)); | |||||
} | |||||
if (hasClone) { | |||||
// user has clone | |||||
String url = getRequestCycle().urlFor(SummaryPage.class, WicketUtils.newRepositoryParameter(clonedRepo)).toString(); | |||||
add(new ExternalLink("myForkLink", url)); | |||||
} else { | |||||
// user does not have clone | |||||
add(new ExternalLink("myForkLink", "").setVisible(false)); | |||||
} | |||||
} else { | |||||
// server prohibits forking | |||||
add(new ExternalLink("forkLink", "").setVisible(false)); | |||||
add(new ExternalLink("myForkLink", "").setVisible(false)); | |||||
} | |||||
super.setupPage(repositoryName, pageName); | super.setupPage(repositoryName, pageName); | ||||
} | } | ||||
} | } | ||||
protected void addRefs(Repository r, RevCommit c) { | protected void addRefs(Repository r, RevCommit c) { | ||||
add(new RefsPanel("refsPanel", repositoryName, c, JGitUtils.getAllRefs(r))); | |||||
add(new RefsPanel("refsPanel", repositoryName, c, JGitUtils.getAllRefs(r, getRepositoryModel().showRemoteBranches))); | |||||
} | } | ||||
protected void addFullText(String wicketId, String text, boolean substituteRegex) { | protected void addFullText(String wicketId, String text, boolean substituteRegex) { |
// remove named repository parameter | // remove named repository parameter | ||||
params.remove("r"); | params.remove("r"); | ||||
// remove named user parameter | |||||
params.remove("user"); | |||||
// remove days back parameter if it is the default value | // remove days back parameter if it is the default value | ||||
if (params.containsKey("db") | if (params.containsKey("db") | ||||
&& params.getInt("db") == GitBlit.getInteger(Keys.web.activityDuration, 14)) { | && params.getInt("db") == GitBlit.getInteger(Keys.web.activityDuration, 14)) { | ||||
boolean hasParameter = false; | boolean hasParameter = false; | ||||
String projectName = WicketUtils.getProjectName(params); | String projectName = WicketUtils.getProjectName(params); | ||||
String userName = WicketUtils.getUsername(params); | |||||
if (StringUtils.isEmpty(projectName)) { | |||||
if (!StringUtils.isEmpty(userName)) { | |||||
projectName = "~" + userName; | |||||
} | |||||
} | |||||
String repositoryName = WicketUtils.getRepositoryName(params); | String repositoryName = WicketUtils.getRepositoryName(params); | ||||
String set = WicketUtils.getSet(params); | String set = WicketUtils.getSet(params); | ||||
String regex = WicketUtils.getRegEx(params); | String regex = WicketUtils.getRegEx(params); |
add(new Label("otherUrls", StringUtils.flattenStrings(repositoryUrls, "<br/>")) | add(new Label("otherUrls", StringUtils.flattenStrings(repositoryUrls, "<br/>")) | ||||
.setEscapeModelStrings(false)); | .setEscapeModelStrings(false)); | ||||
add(new LogPanel("commitsPanel", repositoryName, getRepositoryModel().HEAD, r, numberCommits, 0)); | |||||
add(new LogPanel("commitsPanel", repositoryName, getRepositoryModel().HEAD, r, numberCommits, 0, getRepositoryModel().showRemoteBranches)); | |||||
add(new TagsPanel("tagsPanel", repositoryName, r, numberRefs).hideIfEmpty()); | add(new TagsPanel("tagsPanel", repositoryName, r, numberRefs).hideIfEmpty()); | ||||
add(new BranchesPanel("branchesPanel", getRepositoryModel(), r, numberRefs, false).hideIfEmpty()); | add(new BranchesPanel("branchesPanel", getRepositoryModel(), r, numberRefs, false).hideIfEmpty()); | ||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" | |||||
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" | |||||
xml:lang="en" | |||||
lang="en"> | |||||
<body> | |||||
<wicket:extend> | |||||
<div class="row"> | |||||
<div class="span4"> | |||||
<div wicket:id="gravatar"></div> | |||||
<div style="text-align: left;"> | |||||
<h2><span wicket:id="userDisplayName"></span></h2> | |||||
<div><i class="icon-user"></i> <span wicket:id="userUsername"></span></div> | |||||
<div><i class="icon-envelope"></i><span wicket:id="userEmail"></span></div> | |||||
</div> | |||||
</div> | |||||
<div class="span8"> | |||||
<div class="tabbable"> | |||||
<!-- tab titles --> | |||||
<ul class="nav nav-tabs"> | |||||
<li class="active"><a href="#repositories" data-toggle="tab"><wicket:message key="gb.repositories"></wicket:message></a></li> | |||||
</ul> | |||||
<!-- tab content --> | |||||
<div class="tab-content"> | |||||
<!-- repositories tab --> | |||||
<div class="tab-pane active" id="repositories"> | |||||
<table width="100%"> | |||||
<tbody> | |||||
<tr wicket:id="repositoryList"><td style="border-bottom:1px solid #eee;"><span wicket:id="repository"></span></td></tr> | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</wicket:extend> | |||||
</body> | |||||
</html> |
/* | |||||
* Copyright 2012 gitblit.com. | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
*/ | |||||
package com.gitblit.wicket.pages; | |||||
import java.util.ArrayList; | |||||
import java.util.Collections; | |||||
import java.util.Comparator; | |||||
import java.util.List; | |||||
import org.apache.wicket.PageParameters; | |||||
import org.apache.wicket.RedirectException; | |||||
import org.apache.wicket.markup.html.basic.Label; | |||||
import org.apache.wicket.markup.repeater.Item; | |||||
import org.apache.wicket.markup.repeater.data.DataView; | |||||
import org.apache.wicket.markup.repeater.data.ListDataProvider; | |||||
import org.eclipse.jgit.lib.PersonIdent; | |||||
import com.gitblit.GitBlit; | |||||
import com.gitblit.Keys; | |||||
import com.gitblit.models.ProjectModel; | |||||
import com.gitblit.models.RepositoryModel; | |||||
import com.gitblit.models.UserModel; | |||||
import com.gitblit.utils.StringUtils; | |||||
import com.gitblit.wicket.GitBlitWebApp; | |||||
import com.gitblit.wicket.GitBlitWebSession; | |||||
import com.gitblit.wicket.PageRegistration; | |||||
import com.gitblit.wicket.PageRegistration.DropDownMenuItem; | |||||
import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration; | |||||
import com.gitblit.wicket.WicketUtils; | |||||
import com.gitblit.wicket.panels.GravatarImage; | |||||
import com.gitblit.wicket.panels.LinkPanel; | |||||
import com.gitblit.wicket.panels.ProjectRepositoryPanel; | |||||
public class UserPage extends RootPage { | |||||
List<ProjectModel> projectModels = new ArrayList<ProjectModel>(); | |||||
public UserPage() { | |||||
super(); | |||||
throw new RedirectException(GitBlitWebApp.get().getHomePage()); | |||||
} | |||||
public UserPage(PageParameters params) { | |||||
super(params); | |||||
setup(params); | |||||
} | |||||
@Override | |||||
protected boolean reusePageParameters() { | |||||
return true; | |||||
} | |||||
private void setup(PageParameters params) { | |||||
setupPage("", ""); | |||||
// check to see if we should display a login message | |||||
boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, true); | |||||
if (authenticateView && !GitBlitWebSession.get().isLoggedIn()) { | |||||
authenticationError("Please login"); | |||||
return; | |||||
} | |||||
String userName = WicketUtils.getUsername(params); | |||||
if (StringUtils.isEmpty(userName)) { | |||||
throw new RedirectException(GitBlitWebApp.get().getHomePage()); | |||||
} | |||||
UserModel user = GitBlit.self().getUserModel(userName); | |||||
if (user == null) { | |||||
// construct a temporary user model | |||||
user = new UserModel(userName); | |||||
} | |||||
String projectName = "~" + userName; | |||||
ProjectModel project = GitBlit.self().getProjectModel(projectName); | |||||
if (project == null) { | |||||
throw new RedirectException(GitBlitWebApp.get().getHomePage()); | |||||
} | |||||
add(new Label("userDisplayName", user.getDisplayName())); | |||||
add(new Label("userUsername", user.username)); | |||||
LinkPanel email = new LinkPanel("userEmail", null, user.emailAddress, "mailto:#"); | |||||
email.setRenderBodyOnly(true); | |||||
add(email.setVisible(GitBlit.getBoolean(Keys.web.showEmailAddresses, true) && !StringUtils.isEmpty(user.emailAddress))); | |||||
PersonIdent person = new PersonIdent(user.getDisplayName(), user.emailAddress); | |||||
add(new GravatarImage("gravatar", person, 210)); | |||||
List<RepositoryModel> repositories = getRepositories(params); | |||||
Collections.sort(repositories, new Comparator<RepositoryModel>() { | |||||
@Override | |||||
public int compare(RepositoryModel o1, RepositoryModel o2) { | |||||
// reverse-chronological sort | |||||
return o2.lastChange.compareTo(o1.lastChange); | |||||
} | |||||
}); | |||||
final ListDataProvider<RepositoryModel> dp = new ListDataProvider<RepositoryModel>(repositories); | |||||
DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("repositoryList", dp) { | |||||
private static final long serialVersionUID = 1L; | |||||
public void populateItem(final Item<RepositoryModel> item) { | |||||
final RepositoryModel entry = item.getModelObject(); | |||||
ProjectRepositoryPanel row = new ProjectRepositoryPanel("repository", | |||||
getLocalizer(), this, showAdmin, entry, getAccessRestrictions()); | |||||
item.add(row); | |||||
} | |||||
}; | |||||
add(dataView); | |||||
} | |||||
@Override | |||||
protected void addDropDownMenus(List<PageRegistration> pages) { | |||||
PageParameters params = getPageParameters(); | |||||
DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters", | |||||
UserPage.class); | |||||
// preserve time filter option on repository choices | |||||
menu.menuItems.addAll(getRepositoryFilterItems(params)); | |||||
// preserve repository filter option on time choices | |||||
menu.menuItems.addAll(getTimeFilterItems(params)); | |||||
if (menu.menuItems.size() > 0) { | |||||
// Reset Filter | |||||
menu.menuItems.add(new DropDownMenuItem(getString("gb.reset"), null, null)); | |||||
} | |||||
pages.add(menu); | |||||
} | |||||
} |
public GravatarImage(String id, PersonIdent person, int width) { | public GravatarImage(String id, PersonIdent person, int width) { | ||||
super(id); | super(id); | ||||
String email = person.getEmailAddress().toLowerCase(); | |||||
String email = person.getEmailAddress() == null ? person.getName().toLowerCase() : person.getEmailAddress().toLowerCase(); | |||||
String hash = StringUtils.getMD5(email); | String hash = StringUtils.getMD5(email); | ||||
Link<Void> link = new BookmarkablePageLink<Void>("link", GravatarProfilePage.class, | Link<Void> link = new BookmarkablePageLink<Void>("link", GravatarProfilePage.class, | ||||
WicketUtils.newObjectParameter(hash)); | WicketUtils.newObjectParameter(hash)); |
private boolean hasMore; | private boolean hasMore; | ||||
public HistoryPanel(String wicketId, final String repositoryName, final String objectId, | public HistoryPanel(String wicketId, final String repositoryName, final String objectId, | ||||
final String path, Repository r, int limit, int pageOffset) { | |||||
final String path, Repository r, int limit, int pageOffset, boolean showRemoteRefs) { | |||||
super(wicketId); | super(wicketId); | ||||
boolean pageResults = limit <= 0; | boolean pageResults = limit <= 0; | ||||
int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50); | int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50); | ||||
} | } | ||||
final boolean isTree = matchingPath == null ? true : matchingPath.isTree(); | final boolean isTree = matchingPath == null ? true : matchingPath.isTree(); | ||||
final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r); | |||||
final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs); | |||||
List<RevCommit> commits; | List<RevCommit> commits; | ||||
if (pageResults) { | if (pageResults) { | ||||
// Paging result set | // Paging result set |
private boolean hasMore; | private boolean hasMore; | ||||
public LogPanel(String wicketId, final String repositoryName, final String objectId, | public LogPanel(String wicketId, final String repositoryName, final String objectId, | ||||
Repository r, int limit, int pageOffset) { | |||||
Repository r, int limit, int pageOffset, boolean showRemoteRefs) { | |||||
super(wicketId); | super(wicketId); | ||||
boolean pageResults = limit <= 0; | boolean pageResults = limit <= 0; | ||||
int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50); | int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50); | ||||
itemsPerPage = 50; | itemsPerPage = 50; | ||||
} | } | ||||
final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r); | |||||
final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs); | |||||
List<RevCommit> commits; | List<RevCommit> commits; | ||||
if (pageResults) { | if (pageResults) { | ||||
// Paging result set | // Paging result set |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||||
<html xmlns="http://www.w3.org/1999/xhtml" | |||||
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" | |||||
xml:lang="en" | |||||
lang="en"> | |||||
<wicket:panel> | |||||
<wicket:fragment wicket:id="repositoryAdminLinks"> | |||||
<span class="link"> | |||||
<a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | |||||
| <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | |||||
| <a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a> | |||||
| <a wicket:id="deleteRepository"><wicket:message key="gb.delete">[delete]</wicket:message></a> | |||||
</span> | |||||
</wicket:fragment> | |||||
<wicket:fragment wicket:id="repositoryOwnerLinks"> | |||||
<span class="link"> | |||||
<a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | |||||
| <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | |||||
| <a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a> | |||||
</span> | |||||
</wicket:fragment> | |||||
<wicket:fragment wicket:id="repositoryUserLinks"> | |||||
<span class="link"> | |||||
<a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | |||||
| <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | |||||
</span> | |||||
</wicket:fragment> | |||||
<wicket:fragment wicket:id="originFragment"> | |||||
<p class="originRepository" style="margin-left:20px;" ><wicket:message key="gb.forkedFrom">[forked from]</wicket:message> <span wicket:id="originRepository">[origin repository]</span></p> | |||||
</wicket:fragment> | |||||
<div> | |||||
<div style="padding-top:15px;padding-bottom:15px;margin-right:15px;"> | |||||
<div class="pull-right" style="text-align:right;padding-right:15px;"> | |||||
<span wicket:id="repositoryLinks"></span> | |||||
<div> | |||||
<img class="inlineIcon" wicket:id="frozenIcon" /> | |||||
<img class="inlineIcon" wicket:id="federatedIcon" /> | |||||
<a style="text-decoration: none;" wicket:id="tickets" wicket:message="title:gb.tickets"> | |||||
<img style="border:0px;vertical-align:middle;" src="bug_16x16.png"></img> | |||||
</a> | |||||
<a style="text-decoration: none;" wicket:id="docs" wicket:message="title:gb.docs"> | |||||
<img style="border:0px;vertical-align:middle;" src="book_16x16.png"></img> | |||||
</a> | |||||
<a style="text-decoration: none;" wicket:id="syndication" wicket:message="title:gb.feed"> | |||||
<img style="border:0px;vertical-align:middle;" src="feed_16x16.png"></img> | |||||
</a> | |||||
</div> | |||||
<span style="color: #999;font-style:italic;font-size:0.8em;" wicket:id="repositoryOwner">[owner]</span> | |||||
</div> | |||||
<div class="pageTitle" style="border:0px;"> | |||||
<div> | |||||
<span class="repositorySwatch" wicket:id="repositorySwatch"></span> | |||||
<span class="repository" style="padding-left:3px;color:black;" wicket:id="repositoryName">[repository name]</span> | |||||
<img class="inlineIcon" style="vertical-align:baseline" wicket:id="accessRestrictionIcon" /> | |||||
</div> | |||||
<span wicket:id="originRepository">[origin repository]</span> | |||||
</div> | |||||
<div style="padding-left:20px;"> | |||||
<div style="padding-bottom:10px" wicket:id="repositoryDescription">[repository description]</div> | |||||
<div style="color: #999;"> | |||||
<wicket:message key="gb.lastChange">[last change]</wicket:message> <span wicket:id="repositoryLastChange">[last change]</span>, | |||||
<span style="font-size:0.8em;" wicket:id="repositorySize">[repository size]</span> | |||||
</div> | |||||
<div class="hidden-phone hidden-tablet" wicket:id="repositoryCloneUrl">[repository clone url]</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</wicket:panel> | |||||
</html> |
/* | |||||
* Copyright 2012 gitblit.com. | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
*/ | |||||
package com.gitblit.wicket.panels; | |||||
import java.text.MessageFormat; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import org.apache.wicket.Component; | |||||
import org.apache.wicket.Localizer; | |||||
import org.apache.wicket.PageParameters; | |||||
import org.apache.wicket.markup.html.basic.Label; | |||||
import org.apache.wicket.markup.html.link.BookmarkablePageLink; | |||||
import org.apache.wicket.markup.html.link.ExternalLink; | |||||
import org.apache.wicket.markup.html.link.Link; | |||||
import org.apache.wicket.markup.html.panel.Fragment; | |||||
import com.gitblit.Constants.AccessRestrictionType; | |||||
import com.gitblit.GitBlit; | |||||
import com.gitblit.Keys; | |||||
import com.gitblit.SyndicationServlet; | |||||
import com.gitblit.models.RepositoryModel; | |||||
import com.gitblit.models.UserModel; | |||||
import com.gitblit.utils.ArrayUtils; | |||||
import com.gitblit.utils.StringUtils; | |||||
import com.gitblit.wicket.GitBlitWebSession; | |||||
import com.gitblit.wicket.WicketUtils; | |||||
import com.gitblit.wicket.pages.BasePage; | |||||
import com.gitblit.wicket.pages.DocsPage; | |||||
import com.gitblit.wicket.pages.EditRepositoryPage; | |||||
import com.gitblit.wicket.pages.LogPage; | |||||
import com.gitblit.wicket.pages.SummaryPage; | |||||
import com.gitblit.wicket.pages.TicketsPage; | |||||
import com.gitblit.wicket.pages.TreePage; | |||||
public class ProjectRepositoryPanel extends BasePanel { | |||||
private static final long serialVersionUID = 1L; | |||||
public ProjectRepositoryPanel(String wicketId, Localizer localizer, Component owner, | |||||
final boolean isAdmin, final RepositoryModel entry, | |||||
final Map<AccessRestrictionType, String> accessRestrictions) { | |||||
super(wicketId); | |||||
final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true); | |||||
final boolean gitServlet = GitBlit.getBoolean(Keys.git.enableGitServlet, true); | |||||
final boolean showSize = GitBlit.getBoolean(Keys.web.showRepositorySizes, true); | |||||
// repository swatch | |||||
Component swatch; | |||||
if (entry.isBare) { | |||||
swatch = new Label("repositorySwatch", " ").setEscapeModelStrings(false); | |||||
} else { | |||||
swatch = new Label("repositorySwatch", "!"); | |||||
WicketUtils.setHtmlTooltip(swatch, localizer.getString("gb.workingCopyWarning", owner)); | |||||
} | |||||
WicketUtils.setCssBackground(swatch, entry.toString()); | |||||
add(swatch); | |||||
swatch.setVisible(showSwatch); | |||||
PageParameters pp = WicketUtils.newRepositoryParameter(entry.name); | |||||
add(new LinkPanel("repositoryName", "list", StringUtils.getRelativePath(entry.projectPath, | |||||
StringUtils.stripDotGit(entry.name)), SummaryPage.class, pp)); | |||||
add(new Label("repositoryDescription", entry.description).setVisible(!StringUtils | |||||
.isEmpty(entry.description))); | |||||
if (StringUtils.isEmpty(entry.originRepository)) { | |||||
add(new Label("originRepository").setVisible(false)); | |||||
} else { | |||||
Fragment forkFrag = new Fragment("originRepository", "originFragment", this); | |||||
forkFrag.add(new LinkPanel("originRepository", null, StringUtils.stripDotGit(entry.originRepository), | |||||
SummaryPage.class, WicketUtils.newRepositoryParameter(entry.originRepository))); | |||||
add(forkFrag); | |||||
} | |||||
add(new BookmarkablePageLink<Void>("tickets", TicketsPage.class, pp).setVisible(entry.useTickets)); | |||||
add(new BookmarkablePageLink<Void>("docs", DocsPage.class, pp).setVisible(entry.useDocs)); | |||||
if (entry.isFrozen) { | |||||
add(WicketUtils.newImage("frozenIcon", "cold_16x16.png", localizer.getString("gb.isFrozen", owner))); | |||||
} else { | |||||
add(WicketUtils.newClearPixel("frozenIcon").setVisible(false)); | |||||
} | |||||
if (entry.isFederated) { | |||||
add(WicketUtils.newImage("federatedIcon", "federated_16x16.png", localizer.getString("gb.isFederated", owner))); | |||||
} else { | |||||
add(WicketUtils.newClearPixel("federatedIcon").setVisible(false)); | |||||
} | |||||
switch (entry.accessRestriction) { | |||||
case NONE: | |||||
add(WicketUtils.newBlankImage("accessRestrictionIcon").setVisible(false)); | |||||
break; | |||||
case PUSH: | |||||
add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png", | |||||
accessRestrictions.get(entry.accessRestriction))); | |||||
break; | |||||
case CLONE: | |||||
add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png", | |||||
accessRestrictions.get(entry.accessRestriction))); | |||||
break; | |||||
case VIEW: | |||||
add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png", | |||||
accessRestrictions.get(entry.accessRestriction))); | |||||
break; | |||||
default: | |||||
add(WicketUtils.newBlankImage("accessRestrictionIcon")); | |||||
} | |||||
add(new Label("repositoryOwner", StringUtils.isEmpty(entry.owner) ? "" : (entry.owner + " (" | |||||
+ localizer.getString("gb.owner", owner) + ")"))); | |||||
UserModel user = GitBlitWebSession.get().getUser(); | |||||
Fragment repositoryLinks; | |||||
boolean showOwner = user != null && user.username.equalsIgnoreCase(entry.owner); | |||||
// owner of personal repository gets admin powers | |||||
boolean showAdmin = isAdmin || entry.isUsersPersonalRepository(user.username); | |||||
if (showAdmin || showOwner) { | |||||
repositoryLinks = new Fragment("repositoryLinks", showAdmin ? "repositoryAdminLinks" | |||||
: "repositoryOwnerLinks", this); | |||||
repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", EditRepositoryPage.class, | |||||
WicketUtils.newRepositoryParameter(entry.name))); | |||||
if (showAdmin) { | |||||
Link<Void> deleteLink = new Link<Void>("deleteRepository") { | |||||
private static final long serialVersionUID = 1L; | |||||
@Override | |||||
public void onClick() { | |||||
if (GitBlit.self().deleteRepositoryModel(entry)) { | |||||
info(MessageFormat.format(getString("gb.repositoryDeleted"), entry)); | |||||
// TODO dp.remove(entry); | |||||
} else { | |||||
error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), entry)); | |||||
} | |||||
} | |||||
}; | |||||
deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( | |||||
localizer.getString("gb.deleteRepository", owner), entry))); | |||||
repositoryLinks.add(deleteLink); | |||||
} | |||||
} else { | |||||
repositoryLinks = new Fragment("repositoryLinks", "repositoryUserLinks", this); | |||||
} | |||||
repositoryLinks.add(new BookmarkablePageLink<Void>("tree", TreePage.class, WicketUtils | |||||
.newRepositoryParameter(entry.name)).setEnabled(entry.hasCommits)); | |||||
repositoryLinks.add(new BookmarkablePageLink<Void>("log", LogPage.class, WicketUtils | |||||
.newRepositoryParameter(entry.name)).setEnabled(entry.hasCommits)); | |||||
add(repositoryLinks); | |||||
String lastChange; | |||||
if (entry.lastChange.getTime() == 0) { | |||||
lastChange = "--"; | |||||
} else { | |||||
lastChange = getTimeUtils().timeAgo(entry.lastChange); | |||||
} | |||||
Label lastChangeLabel = new Label("repositoryLastChange", lastChange); | |||||
add(lastChangeLabel); | |||||
WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange)); | |||||
if (entry.hasCommits) { | |||||
// Existing repository | |||||
add(new Label("repositorySize", entry.size).setVisible(showSize)); | |||||
} else { | |||||
// New repository | |||||
add(new Label("repositorySize", localizer.getString("gb.empty", owner)).setEscapeModelStrings(false)); | |||||
} | |||||
add(new ExternalLink("syndication", SyndicationServlet.asLink("", entry.name, null, 0))); | |||||
List<String> repositoryUrls = new ArrayList<String>(); | |||||
if (gitServlet) { | |||||
// add the Gitblit repository url | |||||
repositoryUrls.add(BasePage.getRepositoryUrl(entry)); | |||||
} | |||||
repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(entry.name)); | |||||
String primaryUrl = ArrayUtils.isEmpty(repositoryUrls) ? "" : repositoryUrls.remove(0); | |||||
add(new RepositoryUrlPanel("repositoryCloneUrl", primaryUrl)); | |||||
} | |||||
} |
<wicket:fragment wicket:id="groupRepositoryRow"> | <wicket:fragment wicket:id="groupRepositoryRow"> | ||||
<td colspan="1"><span wicket:id="groupName">[group name]</span></td> | <td colspan="1"><span wicket:id="groupName">[group name]</span></td> | ||||
<td colspan="6"><span class="hidden-phone" style="font-weight:normal;color:#666;" wicket:id="groupDescription">[description]</span></td> | |||||
<td colspan="6" style="padding: 2px;"><span class="hidden-phone" style="font-weight:normal;color:#666;" wicket:id="groupDescription">[description]</span></td> | |||||
</wicket:fragment> | </wicket:fragment> | ||||
<wicket:fragment wicket:id="repositoryRow"> | <wicket:fragment wicket:id="repositoryRow"> |
import com.gitblit.wicket.pages.ProjectPage; | import com.gitblit.wicket.pages.ProjectPage; | ||||
import com.gitblit.wicket.pages.RepositoriesPage; | import com.gitblit.wicket.pages.RepositoriesPage; | ||||
import com.gitblit.wicket.pages.SummaryPage; | import com.gitblit.wicket.pages.SummaryPage; | ||||
import com.gitblit.wicket.pages.UserPage; | |||||
public class RepositoriesPanel extends BasePanel { | public class RepositoriesPanel extends BasePanel { | ||||
} | } | ||||
Map<String, ProjectModel> projects = new HashMap<String, ProjectModel>(); | Map<String, ProjectModel> projects = new HashMap<String, ProjectModel>(); | ||||
for (ProjectModel project : GitBlit.self().getProjectModels(user)) { | |||||
for (ProjectModel project : GitBlit.self().getProjectModels(user, true)) { | |||||
projects.put(project.name, project); | projects.put(project.name, project); | ||||
} | } | ||||
List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>(); | List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>(); | ||||
final String baseUrl = WicketUtils.getGitblitURL(getRequest()); | final String baseUrl = WicketUtils.getGitblitURL(getRequest()); | ||||
final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true); | final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true); | ||||
DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) { | DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) { | ||||
private static final long serialVersionUID = 1L; | private static final long serialVersionUID = 1L; | ||||
int counter; | int counter; | ||||
currGroupName = entry.name; | currGroupName = entry.name; | ||||
Fragment row = new Fragment("rowContent", "groupRepositoryRow", this); | Fragment row = new Fragment("rowContent", "groupRepositoryRow", this); | ||||
item.add(row); | item.add(row); | ||||
row.add(new LinkPanel("groupName", null, entry.toString(), ProjectPage.class, WicketUtils.newProjectParameter(entry.name))); | |||||
row.add(new Label("groupDescription", entry.description == null ? "":entry.description)); | |||||
String name = entry.toString(); | |||||
if (name.charAt(0) == '~') { | |||||
// user page | |||||
String username = name.substring(1); | |||||
UserModel user = GitBlit.self().getUserModel(username); | |||||
row.add(new LinkPanel("groupName", null, user == null ? username : user.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(username))); | |||||
row.add(new Label("groupDescription", getString("gb.personalRepositories"))); | |||||
} else { | |||||
// project page | |||||
row.add(new LinkPanel("groupName", null, name, ProjectPage.class, WicketUtils.newProjectParameter(name))); | |||||
row.add(new Label("groupDescription", entry.description == null ? "":entry.description)); | |||||
} | |||||
WicketUtils.setCssClass(item, "group"); | WicketUtils.setCssClass(item, "group"); | ||||
// reset counter so that first row is light background | // reset counter so that first row is light background | ||||
counter = 0; | counter = 0; | ||||
WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange)); | WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange)); | ||||
boolean showOwner = user != null && user.username.equalsIgnoreCase(entry.owner); | boolean showOwner = user != null && user.username.equalsIgnoreCase(entry.owner); | ||||
if (showAdmin) { | |||||
boolean myPersonalRepository = showOwner && entry.isUsersPersonalRepository(user.username); | |||||
if (showAdmin || myPersonalRepository) { | |||||
Fragment repositoryLinks = new Fragment("repositoryLinks", | Fragment repositoryLinks = new Fragment("repositoryLinks", | ||||
"repositoryAdminLinks", this); | "repositoryAdminLinks", this); | ||||
repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", | repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", |
private boolean hasMore; | private boolean hasMore; | ||||
public SearchPanel(String wicketId, final String repositoryName, final String objectId, | public SearchPanel(String wicketId, final String repositoryName, final String objectId, | ||||
final String value, Constants.SearchType searchType, Repository r, int limit, int pageOffset) { | |||||
final String value, Constants.SearchType searchType, Repository r, int limit, int pageOffset, | |||||
boolean showRemoteRefs) { | |||||
super(wicketId); | super(wicketId); | ||||
boolean pageResults = limit <= 0; | boolean pageResults = limit <= 0; | ||||
int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50); | int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50); | ||||
RevCommit commit = JGitUtils.getCommit(r, objectId); | RevCommit commit = JGitUtils.getCommit(r, objectId); | ||||
final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r); | |||||
final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs); | |||||
List<RevCommit> commits; | List<RevCommit> commits; | ||||
if (pageResults) { | if (pageResults) { | ||||
// Paging result set | // Paging result set |