%PDF- %PDF-
Direktori : /proc/985914/root/data/old/home/stash/atlassian-stash/static/util/ |
Current File : //proc/985914/root/data/old/home/stash/atlassian-stash/static/util/navbuilder.js |
define('util/navbuilder', [ 'aui', 'jquery', 'lib/jsuri', 'underscore', 'util/deprecation', 'model/page-state', 'exports' ], function ( _aui, $, Uri, _, deprecate, pageState, exports ) { 'use strict'; // The basic idea of the nav builder is to support a chain of method calls that roughly map to the structure of the // structure and categorisation of parts of Stash. // // E.g. nav.project('foo').repo('bar').permissions() will return a builder that can build the url for the permissions page // of the repository 'bar' of the project 'foo' while just nav.project('foo') will return a builder that for a url to // the project page for project 'foo') // // At each point in the method chain, the returned object will support methods that return a builder // that maps to a concept at a lower level. // At any point, withParams() may be called to add query parameters. // At most points, build() may be called to build the URL to be used. There are a few places where no URL makes sense. // // ** See the unit tests for a description of the urls that can be produced by the nav builder ** /** * Encapsulates a uri path and params that make up a query string. * This class is immutable - all mutating operations return a new instance. */ function PathAndQuery(components, params, anchor) { this.components = (_.isString(components) ? [components] : components) || []; this.params = params || {}; this.anchor = anchor || undefined; } PathAndQuery.prototype.buildRelNoContext = function() { var path = '/' + _.map(this.components, encodeURIComponent).join('/'); var params = _.reduce(this.params, function(memo, values, key) { if (!(_.isArray(values))) { values = [values]; } _.forEach(values, function(value) { memo.push({ key : key, value : value }); }); return memo; }, []); var query = _.map(params, function (param) { var encodedValue = encodeURIComponent(param.value); return encodeURIComponent(param.key) + (encodedValue ? '=' + encodedValue : ''); }).join("&"); return path + (query ? '?' + query : '') + (this.anchor ? '#' + this.anchor : ''); }; PathAndQuery.prototype.buildRelative = function () { return _aui.contextPath() + this.buildRelNoContext(); }; PathAndQuery.prototype.buildAbsolute = function () { return location.protocol + "//" + location.hostname + (location.port ? ':' + location.port : '') + this.buildRelative(); }; PathAndQuery.prototype.toString = function() { return this.buildRelative(); }; /** * Adds query parameters. If a map (object) is supplied, its properties are added to the parameters. * If a single string is supplied, it is added as a query parameter with no value. * @returns a new PathAndQuery object with the updated query params */ PathAndQuery.prototype.addParams = function (params) { var path = new PathAndQuery(this.components, _.extend({}, this.params)); if (_.isString(params)) { path.params[params] = ''; } else { if (params.hasOwnProperty("queryParams")) { path.params = _.extend(path.params, params.queryParams); } else if (!params.hasOwnProperty("urlMode")) { path.params = _.extend(path.params, params); }// todo - implement urlMode } return path; }; /** * Sets the document hash. If a hash has been set previously, it is overwritten * @return a new PathAndQuery object with unchanged path and query string params, but with a new anchor */ PathAndQuery.prototype.withFragment = function (anchor) { return new PathAndQuery(this.components, this.params, anchor); }; /** * Pushes a new path component onto the list of path components. * @returns a new PathAndQuery object with the updated query params */ PathAndQuery.prototype.pushComponents = function() { var path = new PathAndQuery(this.components.slice(0), this.params); _.each(_.toArray(arguments).slice(0), function (component) { if (component !== '') { path.components.push(component); } }); return path; }; /** * Returns a new builder for the current path with the properties supported by otherMethods. * Used after each call in the method chain to construct the next object in the chain and specify * exactly which calls are acceptable. * @returns a new builder */ PathAndQuery.prototype.makeBuilder = function (otherMethods) { var path = this; return _.extend({ _path: function() { return path; }, build: function() { return path.buildRelative(); }, buildAbsolute: function() { return path.buildAbsolute(); }, parse : function() { return parse(this.build()); }, withParams: function(params) { //return a new builder with the same methods as the current builder but with added query parameters return path.addParams(params).makeBuilder(otherMethods); }, withFragment: function (anchor) { return path.withFragment(anchor).makeBuilder(otherMethods); }, addPathComponents: function() { //return a new builder with the same methods as the current builder but with an augmented (new) path return path.pushComponents.apply(path, arguments).makeBuilder(otherMethods); }, toString : function() { // IE8 doesn't call this when using ajax, so we should be consistent and force build() to be called deprecate.getMessageLogger('navbuilder.toString()', 'navbuilder.build()', '2.6', '3.0')(); return this.build(); } }, otherMethods); }; // id/slug/key helpers // If the input is a string, it's the key/slug/id. // Otherwise, if it exists, assume it's a project/repo/PR // Otherwise, use this pageState's project/repo/PR. function getProjectKey(projectOrKey) { if (typeof(projectOrKey) === 'string') { return projectOrKey; } else if (!projectOrKey) { throw new Error(AJS.I18n.getText('stash.web.error.no.project')); } return projectOrKey.getKey ? projectOrKey.getKey() : projectOrKey.key; } function getCurrentProject() { if (pageState.getProject()) { return pageState.getProject(); } throw new Error(AJS.I18n.getText('stash.web.error.no.project.context')); } function getRepoSlug(repoOrSlug) { if (typeof(repoOrSlug) === 'string') { return repoOrSlug; } else if (!repoOrSlug) { throw new Error(AJS.I18n.getText('stash.web.error.no.repo')); } return repoOrSlug.getSlug ? repoOrSlug.getSlug() : repoOrSlug.slug; } function getHookKey(hookOrKey) { if (typeof(hookOrKey) === 'string') { return hookOrKey; } else if (!hookOrKey) { throw new Error(AJS.I18n.getText('stash.web.error.no.hook.key')); } return hookOrKey.getDetails().getKey(); } function getCurrentRepository() { if (pageState.getRepository()) { return pageState.getRepository(); } throw new Error(AJS.I18n.getText('stash.web.error.no.repo.context')); } function getPullRequestId(prOrId) { if (typeof prOrId in {"string":1, "number": 1}) { return prOrId; } else if (!prOrId) { throw new Error(AJS.I18n.getText('stash.web.error.no.pull-request.id')); } return prOrId.getId(); } function getCurrentPullRequest() { if (pageState.getPullRequest()) { return pageState.getPullRequest(); } throw new Error(AJS.I18n.getText('stash.web.error.no.pull-request.context')); } //---------------------------------------- //Start of fluent interface/method chains //---------------------------------------- //--- Methods at the root of the chain --- function login() { return new PathAndQuery('login').makeBuilder({ next : loginNext}); } function tmp() { return new PathAndQuery('tmp').makeBuilder({ avatars: tmpAvatars }); } function admin() { return new PathAndQuery('admin').makeBuilder({ permissions: permissions, users: adminUsers, groups: groups, licensing: licensing, mailServer: mailServer, db : adminDb }); } function restAdmin() { return this._path().pushComponents('admin').makeBuilder({ users: restAdminUsers }); } function allProjects() { return new PathAndQuery('projects').makeBuilder(); } function globalAllRepos() { return new PathAndQuery('repos').makeBuilder({ visibility: allReposWithVisibility }); } function allReposWithVisibility(visibility) { return this._path().addParams({'visibility': visibility}).makeBuilder(); } function captcha() { //Add a changing query param to ensure all browsers reload the image when refreshing it - some don't respect the HTTP headers return new PathAndQuery('captcha').addParams({'ts' : new Date().getTime().toString()}).makeBuilder(); } function project(projectOrKey) { var path = new PathAndQuery(['projects', getProjectKey(projectOrKey)]); return maybeResolveAsUserPath(path).makeBuilder({ allRepos: allRepos, repo: repo, createRepo: createRepo, settings: projSettings, permissions: permissions, remove: projDelete, users: adminUsers, groups: groups, avatar: projAvatar }); } //If the project is a personal project, use the /users/slug form otherwise go with /projects/KEY form function maybeResolveAsUserPath(path) { var projectKey = path.components[1]; var userSlugPattern = /~(.*)/; var result = userSlugPattern.exec(projectKey); if (result) { return new PathAndQuery(['users', result[1].toLowerCase()]); } else { return path; } } function currentProject() { return project(getCurrentProject()); } function createProject() { return new PathAndQuery('projects').addParams('create').makeBuilder(); } function rest(resourcePath) { resourcePath = resourcePath ? resourcePath : 'api'; return new PathAndQuery(['rest', resourcePath, 'latest']).makeBuilder({ project: restProj, currentProject : restCurrentProject, currentRepo: restCurrentRepo, currentPullRequest: restCurrentPullRequest, markup: restMarkup, profile: restProfile, users: restUsers, groups: restGroups, hooks: restTopLevelHooks, allRepos: allRepos, admin: restAdmin }); } function addons() { return new PathAndQuery(['plugins', 'servlet', 'upm']).makeBuilder({ requests: addonsRequests }); } function pluginServlets() { return new PathAndQuery(['plugins', 'servlet']).makeBuilder({ path: servletPath }); } function servletPath() { var path = this._path(); return path.pushComponents.apply(path, componentsFromArguments(arguments)).makeBuilder(); } function addonsRequests() { return this._path().pushComponents('requests', 'popular').makeBuilder({ category: function(category) { return this._path().addParams({category: category}).makeBuilder(); } }); } //--- Methods further down the chain --- function loginNext(url) { return this._path().addParams({ next : url }).makeBuilder(); } function tmpAvatars(){ return this._path().pushComponents('avatars').makeBuilder(); } function permissions() { return this._path().pushComponents('permissions').makeBuilder({ permission: permission, users: adminUsers, groups: groups }); } function permission(name) { return this._path().pushComponents(name).makeBuilder({ users: usersPerm, groups: groupsPerm, all: allPerm }); } function usersPerm() { return this._path().pushComponents('users').makeBuilder(); } function groupsPerm() { return this._path().pushComponents('groups').makeBuilder(); } function allPerm() { return this._path().pushComponents('all').makeBuilder(); } function anonPerm() { return this._path().pushComponents('anon').makeBuilder(); } function nonePerm() { return this._path().pushComponents('none').makeBuilder(); } function allRepos() { return maybeResolveAsUserPath(this._path()).pushComponents('repos').makeBuilder(); } function adminUsers() { return this._path().pushComponents('users').makeBuilder({ create: createEntity, deleteUser: deleteEntity, captcha: adminCaptcha, view: viewEntity, filter: filterEntity, deleteSuccess: deleteSuccess, permissions: permissions, none: nonePerm }); } function restAdminUsers() { return this._path().pushComponents('users').makeBuilder(); } function user(userSlug) { return new PathAndQuery(['users', userSlug]).makeBuilder({ avatar: userAvatar }); } function groups() { return this._path().pushComponents('groups').makeBuilder({ create: createEntity, deleteGroup: deleteEntity, view: viewEntity, filter: filterEntity, deleteSuccess: deleteSuccess, permissions: permissions, none: nonePerm }); } function licensing() { return this._path().pushComponents('license').makeBuilder({ edit: editLicense }); } function editLicense() { return this._path().addParams({edit: ''}).makeBuilder(); } function mailServer() { return this._path().pushComponents('mail-server').makeBuilder(); } function adminDb() { return this._path().pushComponents('db').makeBuilder(); } function createEntity() { return this._path().addParams({create: ''}).makeBuilder(); } function deleteEntity(name) { // delete is a reserved keyword return this._path().addParams({name: name}).makeBuilder(); } function adminCaptcha(name) { return this._path().pushComponents('captcha').addParams({name: name}).makeBuilder(); } function viewEntity(name) { return this._path().pushComponents('view').addParams({name: name}).makeBuilder(); } function filterEntity(filterValue) { return this._path().addParams({filter: filterValue}).makeBuilder(); } function deleteSuccess(name) { return this._path().addParams({deleted: name}).makeBuilder(); } function createRepo() { return maybeResolveAsUserPath(this._path()).pushComponents('repos').addParams('create').makeBuilder(); } function projDelete() { return this._path().makeBuilder(); } function projSettings() { return this._path().pushComponents('settings').makeBuilder(); } function projAvatar(size) { var builder = this._path().pushComponents('avatar.png'); if (size) { builder = builder.addParams({s: size}); } return builder.makeBuilder(); } function repo(repoOrSlug) { return maybeResolveAsUserPath(this._path()).pushComponents('repos', getRepoSlug(repoOrSlug)).makeBuilder({ browse: repoBrowse, diff : repoDiff, commits: repoCommits, branches: repoBranches, commit: repoCommit, changeset: repoCommit, settings: repoSettings, permissions: permissions, hooks: repoHooks, clone: repoClone, fork: repoFork, allPullRequests: allPullRequests, createPullRequest: createPullRequest, pullRequest: pullRequest, build: function () { return this._path().pushComponents('browse').toString(); //the stem /projects/PROJ/repos is different to the path needed if build() is called } }); } function currentRepo() { return currentProject().repo(pageState.getRepository()); } // pull path components from an arguments object. We all .path('a', 'b') and .path(['a', 'b']) both. function componentsFromArguments(args) { //accept multiple args or accept a single arg that's an array to support .path('a', 'b') and .path(['a', 'b']) if (args.length === 1) { if (args[0] && args[0].getComponents) { // accept a Path object return args[0].getComponents(); } else if ($.isArray(args[0])) { return args[0]; } } return _.toArray(args); } function repoBrowse() { return this._path().pushComponents('browse').makeBuilder({ path: repoBrowsePath, at: repoBrowsePathAt }); } function repoBrowsePath() { var path = this._path(); return path.pushComponents.apply(path, componentsFromArguments(arguments)).makeBuilder({ at: repoBrowsePathAt, until: repoBrowsePathUntil, raw : repoBrowsePathAtRaw }); } function repoBrowsePathAt(then) { var builder = this._path(); if (then) { if (typeof then !== 'string') { then = then.displayId || then; } builder = builder.addParams({ at: then }); } return builder.makeBuilder({ until : repoBrowsePathUntil, raw : repoBrowsePathAtRaw }); } function repoBrowsePathUntil(then) { return this._path().addParams({until: then}).makeBuilder({ at: repoBrowsePathAt, raw : repoBrowsePathAtRaw }); } function repoBrowsePathAtRaw() { return this._path().addParams({raw: ''}).makeBuilder(); } function repoDiff(fileChangeOrPath) { var builder = this._path(), path; // Duck-type as adding FileChange as a dependency on navbuilder causes too much recursion in dependency stack var isFileChange = ( fileChangeOrPath.getCommitRange && fileChangeOrPath.getPath && fileChangeOrPath.getSrcPath ); if (isFileChange) { var commitRange = fileChangeOrPath.getCommitRange(); path = fileChangeOrPath.getPath(); if (commitRange.getPullRequest()) { builder = builder.pushComponents('pull-requests', commitRange.getPullRequest().getId()); } else { builder = builder.addParams($.extend({}, { until: commitRange.getUntilRevision() && commitRange.getUntilRevision().getId() })); var since = commitRange.getSinceRevision() && commitRange.getSinceRevision().getId(); if (since) { builder = builder.addParams({ since: since }); } } } else { path = fileChangeOrPath; } builder = builder.pushComponents('diff'); //need to do this separately otherwise we don't have the correct context for the next apply invocation. builder = builder.pushComponents.apply(builder, path && componentsFromArguments([path])); if (isFileChange && fileChangeOrPath.getSrcPath()) { builder = builder.addParams($.extend({}, { srcPath: fileChangeOrPath.getSrcPath().toString() })); } return builder.makeBuilder({ at: repoDiffAt }); } function repoDiffAt(then) { return this._path().addParams({at: then}).makeBuilder(); } function repoCommits() { return this._path().pushComponents('commits').makeBuilder({ until:repoCommitsUntil }); } function repoBranches(baseRef) { var builder = this._path().pushComponents('branches'); if (baseRef && !baseRef.isDefault) { if (typeof baseRef !== 'string') { baseRef = baseRef.displayId || baseRef.id || baseRef; } builder = builder.addParams({ base: baseRef }); } return builder.makeBuilder(); } function repoCommitsUntil(until) { var builder = this._path(); if (until && !until.isDefault) { if (typeof until !== 'string') { until = until.displayId || until; } builder = builder.addParams({ until: until }); } return builder.makeBuilder(); } function repoCommit(commitId) { // commitId must be SHA1 hash return this._path().pushComponents('commits', commitId).makeBuilder({ comment: repoCommitComment }); } function repoCommitComment(commentId) { return this._path().addParams({ commentId: commentId }).makeBuilder(); } function repoSettings() { return this._path().pushComponents('settings').makeBuilder(); } function repoHooks() { return this._path().pushComponents('settings', 'hooks').makeBuilder(); } function repoClone(dcvsKind) { var path = this._path(), projectKey = path.components[1].toLowerCase(), repoSlug = path.components[3].toLowerCase(); if (path.components[0] === 'users') { projectKey = "~" + projectKey; } return new PathAndQuery(['scm', projectKey, repoSlug + '.' + dcvsKind], path.params).makeBuilder(); } function repoFork() { return this._path().addParams('fork').makeBuilder(); } //--- Pull Request Methods --- function allPullRequests() { return this._path().pushComponents('pull-requests').makeBuilder(); } var prCreateParamBuilders = { sourceBranch: pullRequestSourceBranch, targetBranch: pullRequestTargetBranch, source: deprecate.fn(pullRequestSourceBranch, 'navbuilder.project().repo().createPullRequest().source()', 'navbuilder.project().repo().createPullRequest().sourceBranch()', '2.4', '3.0'), target: deprecate.fn(pullRequestTargetBranch, 'navbuilder.project().repo().createPullRequest().target()', 'navbuilder.project().repo().createPullRequest().targetBranch()', '2.4', '3.0') }; function createPullRequest() { return this._path().pushComponents('pull-requests').addParams('create').makeBuilder(prCreateParamBuilders); } function pullRequestSourceBranch(sourceBranch) { return this._path().addParams({sourceBranch: sourceBranch}).makeBuilder(prCreateParamBuilders); } function pullRequestTargetBranch(targetBranch) { return this._path().addParams({targetBranch: targetBranch}).makeBuilder(prCreateParamBuilders); } function pullRequest(prOrId) { return this._path().pushComponents('pull-requests', getPullRequestId(prOrId)).makeBuilder({ unwatch: pullRequestUnwatch, /** * @deprecated since 2.0. Use overview() instead. */ activity: pullRequestActivity, changeset: pullRequestChangeset, overview: pullRequestOverview, diff: pullRequestDiff, commits: pullRequestCommits, build: function () { return this._path().pushComponents('overview').toString(); //Default to overview view } }); } function currentPullRequest() { return currentRepo.call(this).pullRequest(getCurrentPullRequest()); } var pullRequestActivity = deprecate.fn(pullRequestOverview, 'navbuilder::activity()', 'navbuilder::overview()', '2.0', '3.0'); function pullRequestOverview(){ return this._path().pushComponents('overview').makeBuilder({ comment: pullRequestComment }); } function pullRequestUnwatch(){ return this._path().pushComponents('unwatch').makeBuilder(); } function pullRequestChangeset(changesetId) { //Unlike repository changesets, ref names like "master" are not supported here. As a result, there is //no need to do all the path gyrations repoChangeset does return this._path().pushComponents('commits', changesetId).makeBuilder(); } function pullRequestComment(commentId){ return this._path().addParams({commentId: commentId}).makeBuilder(); } function pullRequestDiff(){ return this._path().pushComponents('diff').makeBuilder({ change: function (diffChangePath) { return this._path().withFragment(diffChangePath).makeBuilder(); } }); } function pullRequestCommits(){ return this._path().pushComponents('commits').makeBuilder(); } function restProj(projectOrKey) { var key = getProjectKey(projectOrKey); return this._path().pushComponents('projects', key).makeBuilder({ allRepos: restAllRepos, repo: restRepo, permissions: restProjPermissions }); } function restCurrentProject() { return restProj.call(this, getCurrentProject()); } function restHook(hookOrKey) { var hookKey = getHookKey(hookOrKey); return this._path().pushComponents('settings').pushComponents('hooks', hookKey).makeBuilder({ enabled: hookEnabled, settings: hookSettings }); } function hookEnabled() { return this._path().pushComponents('enabled').makeBuilder(); } function hookSettings() { return this._path().pushComponents('settings').makeBuilder(); } function restAllRepos() { return this._path().pushComponents('repos').makeBuilder(); } function restRepo(repoOrSlug) { var slug = getRepoSlug(repoOrSlug); return this._path().pushComponents('repos', slug).makeBuilder({ tags: restRepoTags, branches: restRepoBranches, commits : restRepoAllCommits, commit: restRepoCommit, changeset: restRepoCommit, changes: routeChangesRequest, browse: restRepoBrowse, files: restRepoFind, related : restRepoRelated, pullRequest : restPullRequest, allPullRequests : restAllPullRequests, hooks : repoHooks, hook : restHook }); } function restCurrentRepo() { return restCurrentProject.call(this).repo(getCurrentRepository()); } function routeChangesRequest (commitRange) { if (commitRange.getPullRequest()) { return _.bind(restPullRequest, this)(commitRange.getPullRequest()).changes(); } else if (commitRange.getUntilRevision()) { return this.changeset(commitRange).changes(); } else { throw new Error("A valid commit-range is required to retrieve changes"); } } function restRepoRelated() { return this._path().pushComponents('related').makeBuilder(); } function restPullRequest(prOrId) { var id = getPullRequestId(prOrId); return this._path().pushComponents('pull-requests', id).makeBuilder({ activities : function() { return this._path().pushComponents('activities').makeBuilder(); }, approve: restApprove, comment : restComment, comments : function() { return this._path().pushComponents('comments').makeBuilder(); }, changes: restPullRequestChanges, diff: restDiff, watch: restWatch, merge: restMerge, reopen: restReopen, decline: restDecline }); } function restCurrentPullRequest() { return restCurrentRepo.call(this).pullRequest(getCurrentPullRequest()); } function restAllPullRequests() { return this._path().pushComponents('pull-requests').makeBuilder(); } function restComment(id) { return this._path().pushComponents('comments', id).makeBuilder({ comment : restComment }); } function restPullRequestChanges(){ return this._path().pushComponents('changes').makeBuilder(); } function restApprove() { return this._path().pushComponents('approve').makeBuilder(); } function restWatch() { return this._path().pushComponents('watch').makeBuilder(); } function restMerge() { return this._path().pushComponents('merge').makeBuilder(); } function restDecline() { return this._path().pushComponents('decline').makeBuilder(); } function restReopen() { return this._path().pushComponents('reopen').makeBuilder(); } function restRepoTags() { return this._path().pushComponents('tags').makeBuilder(); } function restRepoBranches() { return this._path().pushComponents('branches').makeBuilder(); } function restRepoAllCommits() { return this._path().pushComponents('commits').makeBuilder(); } function restRepoCommit(commitIdOrCommitRange) { var path = this._path().pushComponents('commits'); if (typeof commitIdOrCommitRange === 'string') { path = path.pushComponents(commitIdOrCommitRange); } else if (commitIdOrCommitRange.getUntilRevision) { path = path.pushComponents(commitIdOrCommitRange.getUntilRevision().getId()); var sinceId = commitIdOrCommitRange.getSinceRevision() && commitIdOrCommitRange.getSinceRevision().getId(); if (sinceId) { path = path.addParams({ since: sinceId }); } } else { throw new Error(AJS.I18n.getText('stash.web.error.no.commit.or.commitRange')); } return path.makeBuilder({ diff: restDiff, changes: restChangesetChanges, comments: restChangesetComment, watch: restCommitWatch }); } function restCommitWatch() { return this._path().pushComponents('watch').makeBuilder(); } function restChangesetChanges() { return this._path().pushComponents('changes').makeBuilder({ path: restChangesetPath }); } function restDiff(fileChange) { var builder = this._path(); builder = builder.pushComponents('diff'); builder = builder.pushComponents.apply(builder, componentsFromArguments([fileChange.getPath()])); if (fileChange.getSrcPath()) { builder = builder.addParams({ srcPath: fileChange.getSrcPath().toString() }); } return builder.makeBuilder(); } function restChangesetComment() { return this._path().pushComponents('comments').makeBuilder({ path: restChangesetPath }); } function restChangesetPath(path) { return this._path().addParams({ path: path.toString() }).makeBuilder(); } function restRepoBrowse() { return this._path().pushComponents('browse').makeBuilder({ path: repoBrowsePath, at: repoBrowsePathAt }); } function restRepoFind() { return this._path().pushComponents('files').makeBuilder({ all: restRepoAllFiles, path: restRepoFilesInPath, at: repoBrowsePathAt }); } function restRepoAllFiles() { return this._path().addParams({limit: 100000}).makeBuilder({ path: restRepoFilesInPath, at: repoBrowsePathAt }); } function restRepoFilesInPath() { var path = this._path(); return path.pushComponents.apply(path, componentsFromArguments(arguments)).makeBuilder({ at: repoBrowsePathAt }); } function restProjPermissions() { return this._path().pushComponents('permissions').makeBuilder({ projectRead: restProjReadPerms, projectWrite: restProjWritePerms }); } function restProjReadPerms() { return this._path().pushComponents('project-read').makeBuilder({ all: restAllProjPerms, anon: restAnonProReadPerms }); } function restProjWritePerms() { return this._path().pushComponents('project-write').makeBuilder({ all: restAllProjPerms }); } function restAllProjPerms() { return this._path().pushComponents('all').makeBuilder({ allow: restAllowProjPerms }); } function restAnonProReadPerms() { return this._path().pushComponents('anon').makeBuilder({ allow: restAllowProjPerms }); } function restAllowProjPerms(allow) { return this._path().addParams({'allow': allow}).makeBuilder(); } function restMarkup() { return this._path().pushComponents('markup').makeBuilder({ preview: restMarkupPreview }); } function restMarkupPreview() { return this._path().pushComponents('preview').makeBuilder(); } function restProfile() { return this._path().pushComponents('profile').makeBuilder({ recent: restProfileRecent }); } function restProfileRecent() { return this._path().pushComponents('recent').makeBuilder({ repos: restProfileRecentRepos }); } function restProfileRecentRepos() { return this._path().pushComponents('repos').makeBuilder(); } function restUsers(userSlug) { var builder = this._path().pushComponents('users'); if (userSlug) { builder = builder.pushComponents(userSlug); } return builder.makeBuilder({ avatar: userAvatar }); } function restGroups() { return this._path().pushComponents('groups').makeBuilder(); } function restTopLevelHooks() { return this._path().pushComponents('hooks').makeBuilder({ hook: restTopLevelHook }); } function restTopLevelHook(hookKey) { return this._path().pushComponents(hookKey).makeBuilder({ avatar: restHookAvatar }); } function restHookAvatar(version) { return this._path().pushComponents('avatar').addParams({'version': version}).makeBuilder(); } function restRepoSearch() { return this._path().pushComponents('repos').makeBuilder(); } function userAvatar(size) { var builder = this._path().pushComponents('avatar.png'); if (size) { builder = builder.addParams({s: size}); } return builder.makeBuilder(); } // HACKY CODE CHECK: off var fallbackUrlPattern = /(default-avatar-)\d+(\.png)/; function avatarUrl(person, size) { return { build : function() { var uri = parse(person.avatarUrl); if (uri.getQueryParamValue("s")) { uri.replaceQueryParam("s", size); } return uri.toString().replace(fallbackUrlPattern, "$1" + size + "$2"); } }; } // HACKY CODE CHECK: on /* Parse URIs */ function parse(uri) { return new Uri(uri); } //Append trailing slash to url if there isn't one already. function appendSlashToUrl(url) { if (typeof url !== 'string') { return '/'; } else { return url + ((url.charAt(url.length - 1) !== '/') ? '/' : ''); } } function newBuilder(components, params) { return new PathAndQuery(components, params); } exports.login = login; exports.tmp = tmp; exports.captcha = captcha; exports.admin = admin; exports.user = user; exports.project = project; exports.pluginServlets = pluginServlets; exports.addons = addons; exports.allProjects = allProjects; exports.allRepos = globalAllRepos; exports.createProject = createProject; exports.currentProject = currentProject; exports.currentRepo = currentRepo; exports.currentPullRequest = currentPullRequest; exports.rest = rest; exports.parse = parse; exports.appendSlashToUrl = appendSlashToUrl; exports.avatarUrl = avatarUrl; exports.newBuilder = newBuilder; });