Preliminary implementation of server-side forking (issue-137)
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.
6 files added
38 files modified
| | |
| | | <?xml version="1.0" encoding="UTF-8"?>
|
| | | <projectDescription>
|
| | | <name>gitblit</name>
|
| | | <name>Gitblit</name> |
| | | <comment></comment>
|
| | | <projects>
|
| | | </projects>
|
| | |
| | |
|
| | | #### 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
|
| | |
|
| | |
| | | ### IDEAS
|
| | |
|
| | | * 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: implement branch permission controls as Groovy pre-receive script.
|
| | | *Maintain permissions text file similar to a gitolite configuration file or svn authz file.*
|
| | |
| | | outline: none;
|
| | | }
|
| | |
|
| | | [class^="icon-"], [class*=" icon-"] a i {
|
| | | /* override for a links that look like bootstrap buttons */
|
| | | vertical-align: text-bottom;
|
| | | }
|
| | |
|
| | | hr {
|
| | | margin-top: 10px;
|
| | | margin-bottom: 10px;
|
| | |
| | | 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 {
|
| | | clear: both;
|
| | | height: 17px;
|
| | |
| | | if (model.canAdmin) {
|
| | | roles.add(Constants.ADMIN_ROLE);
|
| | | }
|
| | | if (model.canFork) {
|
| | | roles.add(Constants.FORK_ROLE);
|
| | | }
|
| | | if (model.excludeFromFederation) {
|
| | | roles.add(Constants.NOT_FEDERATED_ROLE);
|
| | | }
|
| | |
| | | Set<String> roles = new HashSet<String>(Arrays.asList(config.getStringList(
|
| | | USER, username, ROLE)));
|
| | | user.canAdmin = roles.contains(Constants.ADMIN_ROLE);
|
| | | user.canFork = roles.contains(Constants.FORK_ROLE);
|
| | | user.excludeFromFederation = roles.contains(Constants.NOT_FEDERATED_ROLE);
|
| | |
|
| | | // repository memberships
|
| | |
| | | public static final String JGIT_VERSION = "JGit 2.1.0 (201209190230-r)";
|
| | |
|
| | | public static final String ADMIN_ROLE = "#admin";
|
| | | |
| | | public static final String FORK_ROLE = "#fork";
|
| | |
|
| | | public static final String NOT_FEDERATED_ROLE = "#notfederated";
|
| | |
|
| | |
| | | // Permissions
|
| | | if (role.equalsIgnoreCase(Constants.ADMIN_ROLE)) {
|
| | | model.canAdmin = true;
|
| | | } else if (role.equalsIgnoreCase(Constants.FORK_ROLE)) {
|
| | | model.canFork = true;
|
| | | } else if (role.equalsIgnoreCase(Constants.NOT_FEDERATED_ROLE)) {
|
| | | model.excludeFromFederation = true;
|
| | | }
|
| | |
| | | if (model.canAdmin) {
|
| | | roles.add(Constants.ADMIN_ROLE);
|
| | | }
|
| | | if (model.canFork) {
|
| | | roles.add(Constants.FORK_ROLE);
|
| | | }
|
| | | if (model.excludeFromFederation) {
|
| | | roles.add(Constants.NOT_FEDERATED_ROLE);
|
| | | }
|
| | |
| | | import java.io.InputStream;
|
| | | import java.io.InputStreamReader;
|
| | | import java.lang.reflect.Field;
|
| | | import java.net.URI;
|
| | | import java.net.URISyntaxException;
|
| | | import java.text.MessageFormat;
|
| | | import java.text.SimpleDateFormat;
|
| | | import java.util.ArrayList;
|
| | |
| | | private void addToCachedRepositoryList(String name, RepositoryModel model) {
|
| | | if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
|
| | | 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.
|
| | | *
|
| | | * @param name
|
| | | * @return the model being removed
|
| | | */
|
| | | private void removeFromCachedRepositoryList(String name) {
|
| | | private RepositoryModel removeFromCachedRepositoryList(String name) {
|
| | | if (StringUtils.isEmpty(name)) {
|
| | | return;
|
| | | return null;
|
| | | }
|
| | | repositoryListCache.remove(name);
|
| | | return repositoryListCache.remove(name);
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | * @return project config map
|
| | | */
|
| | | private Map<String, ProjectModel> getProjectConfigs() {
|
| | | if (projectConfigs.isOutdated()) {
|
| | | if (projectCache.isEmpty() || projectConfigs.isOutdated()) {
|
| | |
|
| | | try {
|
| | | projectConfigs.load();
|
| | |
| | | * Returns a list of project models for the user.
|
| | | *
|
| | | * @param user
|
| | | * @param includeUsers
|
| | | * @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();
|
| | |
|
| | | // per-user project lists, this accounts for security and visibility
|
| | |
| | | }
|
| | |
|
| | | // sort projects, root project first
|
| | | List<ProjectModel> projects = new ArrayList<ProjectModel>(map.values());
|
| | | 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 a project model, or null if it does not exist
|
| | | */
|
| | | public ProjectModel getProjectModel(String name, UserModel user) {
|
| | | for (ProjectModel project : getProjectModels(user)) {
|
| | | for (ProjectModel project : getProjectModels(user, true)) {
|
| | | if (project.name.equalsIgnoreCase(name)) {
|
| | | return project;
|
| | | }
|
| | |
| | | Map<String, ProjectModel> configs = getProjectConfigs();
|
| | | ProjectModel project = configs.get(name.toLowerCase());
|
| | | 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);
|
| | | }
|
| | | 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;
|
| | | }
|
| | |
| | | model.hasCommits = JGitUtils.hasCommits(r);
|
| | | model.lastChange = JGitUtils.getLastChange(r);
|
| | | model.isBare = r.isBare();
|
| | | if (repositoryName.indexOf('/') == -1) {
|
| | | model.projectPath = "";
|
| | | } else {
|
| | | model.projectPath = repositoryName.substring(0, repositoryName.indexOf('/'));
|
| | | }
|
| | |
|
| | | StoredConfig config = r.getConfig();
|
| | | boolean hasOrigin = !StringUtils.isEmpty(config.getString("remote", "origin", "url"));
|
| | | |
| | | if (config != null) {
|
| | | model.description = getConfig(config, "description", "");
|
| | | model.owner = getConfig(config, "owner", "");
|
| | | model.useTickets = getConfig(config, "useTickets", false);
|
| | | model.useDocs = getConfig(config, "useDocs", false);
|
| | | model.allowForks = getConfig(config, "allowForks", true);
|
| | | model.accessRestriction = AccessRestrictionType.fromName(getConfig(config,
|
| | | "accessRestriction", settings.getString(Keys.git.defaultAccessRestriction, null)));
|
| | | model.authorizationControl = AuthorizationControl.fromName(getConfig(config,
|
| | | "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.showReadme = getConfig(config, "showReadme", false);
|
| | | model.skipSizeCalculation = getConfig(config, "skipSizeCalculation", false);
|
| | |
| | | model.HEAD = JGitUtils.getHEADRef(r);
|
| | | model.availableRefs = JGitUtils.getAvailableHeadTargets(r);
|
| | | 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;
|
| | | }
|
| | |
|
| | |
| | | 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
|
| | | clearRepositoryMetadataCache(repositoryName);
|
| | | repository.resetDisplayName();
|
| | | }
|
| | |
|
| | | // load repository
|
| | |
| | | config.setString(Constants.CONFIG_GITBLIT, null, "owner", repository.owner);
|
| | | config.setBoolean(Constants.CONFIG_GITBLIT, null, "useTickets", repository.useTickets);
|
| | | 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, "authorizationControl", repository.authorizationControl.name());
|
| | | config.setBoolean(Constants.CONFIG_GITBLIT, null, "showRemoteBranches", repository.showRemoteBranches);
|
| | |
| | | closeRepository(repositoryName);
|
| | | // clear the repository cache
|
| | | clearRepositoryMetadataCache(repositoryName);
|
| | | removeFromCachedRepositoryList(repositoryName);
|
| | | |
| | | RepositoryModel model = removeFromCachedRepositoryList(repositoryName);
|
| | | if (!ArrayUtils.isEmpty(model.forks)) {
|
| | | resetRepositoryListCache();
|
| | | }
|
| | |
|
| | | File folder = new File(repositoriesFolder, repositoryName);
|
| | | if (folder.exists() && folder.isDirectory()) {
|
| | |
| | | scheduledExecutor.shutdownNow();
|
| | | 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,
|
| | | offset, length);
|
| | | }
|
| | | Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository);
|
| | | Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository, model.showRemoteBranches);
|
| | |
|
| | | // convert RevCommit to SyndicatedEntryModel
|
| | | for (RevCommit commit : commits) {
|
| | |
| | | this.title = "";
|
| | | this.description = "";
|
| | | }
|
| | | |
| | | public boolean isUserProject() {
|
| | | return name.charAt(0) == '~';
|
| | | }
|
| | |
|
| | | public boolean hasRepository(String name) {
|
| | | return repositories.contains(name.toLowerCase());
|
| | |
| | | import java.util.Date;
|
| | | import java.util.List;
|
| | | import java.util.Map;
|
| | | import java.util.Set;
|
| | | import java.util.TreeSet;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.Constants.AuthorizationControl;
|
| | |
| | | public List<String> postReceiveScripts;
|
| | | public List<String> mailingLists;
|
| | | public Map<String, String> customFields;
|
| | | public String projectPath;
|
| | | private String displayName;
|
| | | public boolean allowForks;
|
| | | public Set<String> forks;
|
| | | public String originRepository;
|
| | |
|
| | | public RepositoryModel() {
|
| | | this("", "", "", new Date(0));
|
| | |
| | | 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
|
| | | public String toString() {
|
| | | if (displayName == null) {
|
| | |
| | | public int compareTo(RepositoryModel o) {
|
| | | 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.Set;
|
| | |
|
| | | import com.gitblit.Constants.AccessRestrictionType;
|
| | | import com.gitblit.Constants.AuthorizationControl;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
|
| | |
| | | public String displayName;
|
| | | public String emailAddress;
|
| | | public boolean canAdmin;
|
| | | public boolean canFork;
|
| | | public boolean excludeFromFederation;
|
| | | public final Set<String> repositories = new HashSet<String>();
|
| | | public final Set<TeamModel> teams = new HashSet<TeamModel>();
|
| | |
| | | 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) {
|
| | | return repositories.contains(name.toLowerCase());
|
| | | }
|
| | |
| | | branches.add(objectId);
|
| | | }
|
| | | Map<ObjectId, List<RefModel>> allRefs = JGitUtils
|
| | | .getAllRefs(repository);
|
| | | .getAllRefs(repository, model.showRemoteBranches);
|
| | |
|
| | | for (String branch : branches) {
|
| | | String shortName = branch;
|
| | |
| | | * @return all refs grouped by their referenced object id
|
| | | */
|
| | | 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);
|
| | | Map<ObjectId, List<RefModel>> refs = new HashMap<ObjectId, List<RefModel>>();
|
| | | for (RefModel ref : list) {
|
| | | if (!includeRemoteRefs && ref.getName().startsWith(Constants.R_REMOTES)) {
|
| | | continue;
|
| | | }
|
| | | ObjectId objectid = ref.getReferencedObjectId();
|
| | | if (!refs.containsKey(objectid)) {
|
| | | refs.put(objectid, new ArrayList<RefModel>());
|
| | |
| | | * @return the first invalid character found or null if string is acceptable
|
| | | */
|
| | | public static Character findInvalidCharacter(String name) {
|
| | | char[] validChars = { '/', '.', '_', '-' };
|
| | | char[] validChars = { '/', '.', '_', '-', '~' };
|
| | | for (char c : name.toCharArray()) {
|
| | | if (!Character.isLetterOrDigit(c)) {
|
| | | boolean ok = false;
|
| | |
| | | }
|
| | | 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.DocsPage;
|
| | | import com.gitblit.wicket.pages.FederationRegistrationPage;
|
| | | import com.gitblit.wicket.pages.ForksPage;
|
| | | import com.gitblit.wicket.pages.GitSearchPage;
|
| | | import com.gitblit.wicket.pages.GravatarProfilePage;
|
| | | import com.gitblit.wicket.pages.HistoryPage;
|
| | |
| | | import com.gitblit.wicket.pages.TicketPage;
|
| | | import com.gitblit.wicket.pages.TicketsPage;
|
| | | import com.gitblit.wicket.pages.TreePage;
|
| | | import com.gitblit.wicket.pages.UserPage;
|
| | | import com.gitblit.wicket.pages.UsersPage;
|
| | |
|
| | | public class GitBlitWebApp extends WebApplication {
|
| | |
| | | mount("/lucene", LuceneSearchPage.class);
|
| | | mount("/project", ProjectPage.class, "p");
|
| | | 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) {
|
| | |
| | | gb.project = project
|
| | | gb.allProjects = all projects
|
| | | 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.Calendar;
|
| | | import java.util.Collections;
|
| | | import java.util.Comparator;
|
| | | import java.util.Date;
|
| | | import java.util.HashSet;
|
| | | import java.util.LinkedHashMap;
|
| | |
| | | import org.apache.wicket.MarkupContainer;
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.RedirectToUrlException;
|
| | | import org.apache.wicket.RequestCycle;
|
| | | import org.apache.wicket.RestartResponseException;
|
| | | import org.apache.wicket.markup.html.CSSPackageResource;
|
| | | import org.apache.wicket.markup.html.WebPage;
|
| | |
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.utils.TimeUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.LinkPanel;
|
| | |
|
| | |
| | | return req.getServerName();
|
| | | }
|
| | |
|
| | | protected String getRepositoryUrl(RepositoryModel repository) {
|
| | | public static String getRepositoryUrl(RepositoryModel repository) {
|
| | | StringBuilder sb = new StringBuilder();
|
| | | sb.append(WicketUtils.getGitblitURL(getRequestCycle().getRequest()));
|
| | | sb.append(WicketUtils.getGitblitURL(RequestCycle.get().getRequest()));
|
| | | sb.append(Constants.GIT_PATH);
|
| | | sb.append(repository.name);
|
| | |
|
| | |
| | |
|
| | | protected List<ProjectModel> getProjectModels() {
|
| | | final UserModel user = GitBlitWebSession.get().getUser();
|
| | | List<ProjectModel> projects = GitBlit.self().getProjectModels(user);
|
| | | List<ProjectModel> projects = GitBlit.self().getProjectModels(user, true);
|
| | | return projects;
|
| | | }
|
| | |
|
| | |
| | | </wicket:container>
|
| | | </td></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.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><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><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>
|
| | |
| | | form.add(new TextField<String>("description"));
|
| | | form.add(new DropDownChoice<String>("owner", GitBlit.self().getAllUsernames())
|
| | | .setEnabled(GitBlitWebSession.get().canAdmin()));
|
| | | form.add(new CheckBox("allowForks"));
|
| | | form.add(new DropDownChoice<AccessRestrictionType>("accessRestriction", Arrays
|
| | | .asList(AccessRestrictionType.values()), new AccessRestrictionRenderer()));
|
| | | 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.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.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><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><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>
|
| | | </table>
|
| | | </form>
|
| | |
| | | form.add(new TextField<String>("displayName").setEnabled(editDisplayName));
|
| | | form.add(new TextField<String>("emailAddress").setEnabled(editEmailAddress));
|
| | | form.add(new CheckBox("canAdmin"));
|
| | | form.add(new CheckBox("canFork"));
|
| | | form.add(new CheckBox("excludeFromFederation"));
|
| | | form.add(repositories);
|
| | | form.add(teams.setEnabled(editTeams));
|
New file |
| | |
| | | <!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> |
New file |
| | |
| | | /*
|
| | | * 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;
|
| | |
|
| | | SearchPanel search = new SearchPanel("searchPanel", repositoryName, objectId, value,
|
| | | searchType, getRepository(), -1, pageNumber - 1);
|
| | | searchType, getRepository(), -1, pageNumber - 1, getRepositoryModel().showRemoteBranches);
|
| | | boolean hasMore = search.hasMore();
|
| | | add(search);
|
| | |
|
| | |
| | | int nextPage = pageNumber + 1;
|
| | |
|
| | | HistoryPanel history = new HistoryPanel("historyPanel", repositoryName, objectId, path,
|
| | | getRepository(), -1, pageNumber - 1);
|
| | | getRepository(), -1, pageNumber - 1, getRepositoryModel().showRemoteBranches);
|
| | | boolean hasMore = history.hasMore();
|
| | | add(history);
|
| | |
|
| | |
| | | refid = getRepositoryModel().HEAD;
|
| | | }
|
| | | LogPanel logPanel = new LogPanel("logPanel", repositoryName, refid, getRepository(), -1,
|
| | | pageNumber - 1);
|
| | | pageNumber - 1, getRepositoryModel().showRemoteBranches);
|
| | | boolean hasMore = logPanel.hasMore();
|
| | | add(logPanel);
|
| | |
|
| | |
| | | <body>
|
| | | <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="span12">
|
| | |
| | | <div class="markdown" wicket:id="repositoriesMessage">[repositories message]</div>
|
| | | </div>
|
| | | </div>
|
| | | |
| | | <!-- repositories -->
|
| | | <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 class="span6" style="border-bottom:1px solid #eee;" wicket:id="repositoryList">
|
| | | <span wicket:id="repository"></span>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | |
| | | import org.apache.wicket.RedirectException;
|
| | | import org.apache.wicket.behavior.HeaderContributor;
|
| | | 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 org.apache.wicket.markup.repeater.Item;
|
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
| | |
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.ActivityUtils;
|
| | | import com.gitblit.utils.ArrayUtils;
|
| | | import com.gitblit.utils.MarkdownUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebApp;
|
| | |
| | | import com.gitblit.wicket.charting.GoogleLineChart;
|
| | | import com.gitblit.wicket.charting.GooglePieChart;
|
| | | 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 {
|
| | |
|
| | |
| | | }
|
| | | });
|
| | |
|
| | | 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);
|
| | | DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("repository", dp) {
|
| | | 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();
|
| | |
|
| | | // 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);
|
| | |
| | | protected List<ProjectModel> getProjectModels() {
|
| | | if (projectModels.isEmpty()) {
|
| | | final UserModel user = GitBlitWebSession.get().getUser();
|
| | | List<ProjectModel> projects = GitBlit.self().getProjectModels(user);
|
| | | List<ProjectModel> projects = GitBlit.self().getProjectModels(user, false);
|
| | | projectModels.addAll(projects);
|
| | | }
|
| | | return projectModels;
|
| | |
| | |
|
| | | protected List<DropDownMenuItem> getProjectsMenu() {
|
| | | 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;
|
| | | boolean showAllProjects = projects.size() > maxProjects;
|
| | | if (showAllProjects) {
|
| | |
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.ProjectModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.MarkdownUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | |
| | | 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) {
|
| | | setupPage("", "");
|
| | | // check to see if we should display a login message
|
| | |
| | | <!-- page header -->
|
| | | <div class="pageTitle">
|
| | | <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>
|
| | |
| | | <wicket:child />
|
| | | </div>
|
| | |
|
| | | <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>
|
| | | <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">
|
| | | <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: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>
|
| | | </body>
|
| | | </html> |
| | |
| | |
|
| | | import org.apache.wicket.Component;
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.RedirectException;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.DropDownChoice;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | 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.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | |
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.PagesServlet;
|
| | | import com.gitblit.SyndicationServlet;
|
| | | import com.gitblit.models.ProjectModel;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.SubmoduleModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.utils.ArrayUtils;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
| | | import com.gitblit.wicket.PageRegistration.OtherPageLink;
|
| | | import com.gitblit.wicket.SessionlessForm;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation;
|
| | | import com.gitblit.wicket.panels.LinkPanel;
|
| | | import com.gitblit.wicket.panels.NavigationPanel;
|
| | | import com.gitblit.wicket.panels.RefsPanel;
|
| | |
| | | public RepositoryPage(PageParameters params) {
|
| | | super(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");
|
| | | } else {
|
| | | projectName = root;
|
| | | }
|
| | | objectId = WicketUtils.getObject(params);
|
| | |
|
| | |
| | |
|
| | | // standard links
|
| | | 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("log", new PageRegistration("gb.log", LogPage.class, params));
|
| | | pages.put("branches", new PageRegistration("gb.branches", BranchesPage.class, params));
|
| | |
| | | // conditional links
|
| | | Repository r = getRepository();
|
| | | 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
|
| | | if (model.useTickets && TicgitUtils.getTicketsBranch(r) != null) {
|
| | |
| | |
|
| | | @Override
|
| | | protected void setupPage(String repositoryName, String pageName) {
|
| | | add(new LinkPanel("repositoryName", null, StringUtils.stripDotGit(repositoryName),
|
| | | SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryName)));
|
| | | add(new Label("pageName", pageName).setRenderBodyOnly(true));
|
| | | if (getRepositoryModel().isBare) {
|
| | | add(new Label("workingCopy").setVisible(false));
|
| | | 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 {
|
| | | Fragment fragment = new Fragment("workingCopy", "workingCopyFragment", this);
|
| | | // 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));
|
| | | |
| | | // 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) {
|
| | | add(new Label("workingCopyIndicator").setVisible(false));
|
| | | } else {
|
| | | Fragment wc = new Fragment("workingCopyIndicator", "workingCopyFragment", this);
|
| | | Label lbl = new Label("workingCopy", getString("gb.workingCopy"));
|
| | | 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);
|
| | |
| | | }
|
| | |
|
| | | 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) {
|
| | |
| | | // remove named repository parameter
|
| | | params.remove("r");
|
| | |
|
| | | // remove named user parameter
|
| | | params.remove("user");
|
| | |
|
| | | // remove days back parameter if it is the default value
|
| | | if (params.containsKey("db")
|
| | | && params.getInt("db") == GitBlit.getInteger(Keys.web.activityDuration, 14)) {
|
| | |
| | |
|
| | | boolean hasParameter = false;
|
| | | 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 set = WicketUtils.getSet(params);
|
| | | String regex = WicketUtils.getRegEx(params);
|
| | |
| | | add(new Label("otherUrls", StringUtils.flattenStrings(repositoryUrls, "<br/>"))
|
| | | .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 BranchesPanel("branchesPanel", getRepositoryModel(), r, numberRefs, false).hideIfEmpty());
|
| | |
|
New file |
| | |
| | | <!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> |
New file |
| | |
| | | /*
|
| | | * 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) {
|
| | | super(id);
|
| | |
|
| | | String email = person.getEmailAddress().toLowerCase();
|
| | | String email = person.getEmailAddress() == null ? person.getName().toLowerCase() : person.getEmailAddress().toLowerCase();
|
| | | String hash = StringUtils.getMD5(email);
|
| | | Link<Void> link = new BookmarkablePageLink<Void>("link", GravatarProfilePage.class,
|
| | | WicketUtils.newObjectParameter(hash));
|
| | |
| | | private boolean hasMore;
|
| | |
|
| | | 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);
|
| | | boolean pageResults = limit <= 0;
|
| | | int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50);
|
| | |
| | | }
|
| | | 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;
|
| | | if (pageResults) {
|
| | | // Paging result set
|
| | |
| | | private boolean hasMore;
|
| | |
|
| | | 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);
|
| | | boolean pageResults = limit <= 0;
|
| | | int itemsPerPage = GitBlit.getInteger(Keys.web.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;
|
| | | if (pageResults) {
|
| | | // Paging result set
|
New file |
| | |
| | | <!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> |
New file |
| | |
| | | /*
|
| | | * 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">
|
| | | <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:id="repositoryRow">
|
| | |
| | | import com.gitblit.wicket.pages.ProjectPage;
|
| | | import com.gitblit.wicket.pages.RepositoriesPage;
|
| | | import com.gitblit.wicket.pages.SummaryPage;
|
| | | import com.gitblit.wicket.pages.UserPage;
|
| | |
|
| | | public class RepositoriesPanel extends BasePanel {
|
| | |
|
| | |
| | | }
|
| | |
|
| | | 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);
|
| | | }
|
| | | List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>();
|
| | |
| | | currGroupName = entry.name;
|
| | | Fragment row = new Fragment("rowContent", "groupRepositoryRow", this);
|
| | | item.add(row);
|
| | | row.add(new LinkPanel("groupName", null, entry.toString(), ProjectPage.class, WicketUtils.newProjectParameter(entry.name)));
|
| | | |
| | | 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");
|
| | | // reset counter so that first row is light background
|
| | | counter = 0;
|
| | |
| | | WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange));
|
| | |
|
| | | 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",
|
| | | "repositoryAdminLinks", this);
|
| | | repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository",
|
| | |
| | | private boolean hasMore;
|
| | |
|
| | | 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);
|
| | | boolean pageResults = limit <= 0;
|
| | | int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50);
|
| | |
| | |
|
| | | 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;
|
| | | if (pageResults) {
|
| | | // Paging result set
|