You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RepositoryPage.java 25KB

hace 12 años
hace 12 años
hace 12 años
hace 12 años
hace 12 años
hace 12 años
hace 13 años
hace 13 años
hace 12 años
hace 12 años
hace 12 años
hace 12 años
hace 12 años
hace 12 años
hace 13 años
hace 13 años
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. /*
  2. * Copyright 2011 gitblit.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.gitblit.wicket.pages;
  17. import java.io.Serializable;
  18. import java.text.MessageFormat;
  19. import java.util.ArrayList;
  20. import java.util.Arrays;
  21. import java.util.Date;
  22. import java.util.HashMap;
  23. import java.util.LinkedHashMap;
  24. import java.util.LinkedHashSet;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.Set;
  28. import org.apache.wicket.Component;
  29. import org.apache.wicket.PageParameters;
  30. import org.apache.wicket.behavior.SimpleAttributeModifier;
  31. import org.apache.wicket.markup.html.basic.Label;
  32. import org.apache.wicket.markup.html.form.DropDownChoice;
  33. import org.apache.wicket.markup.html.form.TextField;
  34. import org.apache.wicket.markup.html.link.ExternalLink;
  35. import org.apache.wicket.markup.html.panel.Fragment;
  36. import org.apache.wicket.model.IModel;
  37. import org.apache.wicket.model.Model;
  38. import org.apache.wicket.protocol.http.RequestUtils;
  39. import org.apache.wicket.request.target.basic.RedirectRequestTarget;
  40. import org.eclipse.jgit.diff.DiffEntry.ChangeType;
  41. import org.eclipse.jgit.lib.PersonIdent;
  42. import org.eclipse.jgit.lib.Repository;
  43. import org.eclipse.jgit.revwalk.RevCommit;
  44. import org.slf4j.Logger;
  45. import org.slf4j.LoggerFactory;
  46. import com.gitblit.Constants;
  47. import com.gitblit.GitBlit;
  48. import com.gitblit.GitBlitException;
  49. import com.gitblit.Keys;
  50. import com.gitblit.PagesServlet;
  51. import com.gitblit.SyndicationServlet;
  52. import com.gitblit.models.ProjectModel;
  53. import com.gitblit.models.RefModel;
  54. import com.gitblit.models.RepositoryModel;
  55. import com.gitblit.models.SubmoduleModel;
  56. import com.gitblit.models.UserModel;
  57. import com.gitblit.models.UserRepositoryPreferences;
  58. import com.gitblit.utils.ArrayUtils;
  59. import com.gitblit.utils.DeepCopier;
  60. import com.gitblit.utils.JGitUtils;
  61. import com.gitblit.utils.RefLogUtils;
  62. import com.gitblit.utils.StringUtils;
  63. import com.gitblit.utils.TicgitUtils;
  64. import com.gitblit.wicket.CacheControl;
  65. import com.gitblit.wicket.GitBlitWebSession;
  66. import com.gitblit.wicket.PageRegistration;
  67. import com.gitblit.wicket.PageRegistration.OtherPageLink;
  68. import com.gitblit.wicket.SessionlessForm;
  69. import com.gitblit.wicket.WicketUtils;
  70. import com.gitblit.wicket.panels.LinkPanel;
  71. import com.gitblit.wicket.panels.NavigationPanel;
  72. import com.gitblit.wicket.panels.RefsPanel;
  73. public abstract class RepositoryPage extends RootPage {
  74. private final Logger logger = LoggerFactory.getLogger(getClass());
  75. private final String PARAM_STAR = "star";
  76. protected final String projectName;
  77. protected final String repositoryName;
  78. protected final String objectId;
  79. private transient Repository r;
  80. private RepositoryModel m;
  81. private Map<String, SubmoduleModel> submodules;
  82. private final Map<String, PageRegistration> registeredPages;
  83. private boolean showAdmin;
  84. private boolean isOwner;
  85. public RepositoryPage(PageParameters params) {
  86. super(params);
  87. repositoryName = WicketUtils.getRepositoryName(params);
  88. String root =StringUtils.getFirstPathElement(repositoryName);
  89. if (StringUtils.isEmpty(root)) {
  90. projectName = GitBlit.getString(Keys.web.repositoryRootGroupName, "main");
  91. } else {
  92. projectName = root;
  93. }
  94. objectId = WicketUtils.getObject(params);
  95. if (StringUtils.isEmpty(repositoryName)) {
  96. error(MessageFormat.format(getString("gb.repositoryNotSpecifiedFor"), getPageName()), true);
  97. }
  98. if (!getRepositoryModel().hasCommits) {
  99. setResponsePage(EmptyRepositoryPage.class, params);
  100. }
  101. if (getRepositoryModel().isCollectingGarbage) {
  102. error(MessageFormat.format(getString("gb.busyCollectingGarbage"), getRepositoryModel().name), true);
  103. }
  104. if (objectId != null) {
  105. RefModel branch = null;
  106. if ((branch = JGitUtils.getBranch(getRepository(), objectId)) != null) {
  107. UserModel user = GitBlitWebSession.get().getUser();
  108. if (user == null) {
  109. // workaround until get().getUser() is reviewed throughout the app
  110. user = UserModel.ANONYMOUS;
  111. }
  112. boolean canAccess = user.canView(getRepositoryModel(),
  113. branch.reference.getName());
  114. if (!canAccess) {
  115. error(getString("gb.accessDenied"), true);
  116. }
  117. }
  118. }
  119. if (params.containsKey(PARAM_STAR)) {
  120. // set starred state
  121. boolean star = params.getBoolean(PARAM_STAR);
  122. UserModel user = GitBlitWebSession.get().getUser();
  123. if (user != null && user.isAuthenticated) {
  124. UserRepositoryPreferences prefs = user.getPreferences().getRepositoryPreferences(getRepositoryModel().name);
  125. prefs.starred = star;
  126. try {
  127. GitBlit.self().updateUserModel(user.username, user, false);
  128. } catch (GitBlitException e) {
  129. logger.error("Failed to update user " + user.username, e);
  130. error(getString("gb.failedToUpdateUser"), false);
  131. }
  132. }
  133. }
  134. // register the available page links for this page and user
  135. registeredPages = registerPages();
  136. // standard page links
  137. List<PageRegistration> pages = new ArrayList<PageRegistration>(registeredPages.values());
  138. NavigationPanel navigationPanel = new NavigationPanel("repositoryNavPanel", getRepoNavPageClass(), pages);
  139. add(navigationPanel);
  140. add(new ExternalLink("syndication", SyndicationServlet.asLink(getRequest()
  141. .getRelativePathPrefixToContextRoot(), repositoryName, null, 0)));
  142. // add floating search form
  143. SearchForm searchForm = new SearchForm("searchForm", repositoryName);
  144. add(searchForm);
  145. searchForm.setTranslatedAttributes();
  146. // set stateless page preference
  147. setStatelessHint(true);
  148. }
  149. @Override
  150. protected Class<? extends BasePage> getRootNavPageClass() {
  151. return RepositoriesPage.class;
  152. }
  153. protected Class<? extends BasePage> getRepoNavPageClass() {
  154. return getClass();
  155. }
  156. private Map<String, PageRegistration> registerPages() {
  157. PageParameters params = null;
  158. if (!StringUtils.isEmpty(repositoryName)) {
  159. params = WicketUtils.newRepositoryParameter(repositoryName);
  160. }
  161. Map<String, PageRegistration> pages = new LinkedHashMap<String, PageRegistration>();
  162. Repository r = getRepository();
  163. RepositoryModel model = getRepositoryModel();
  164. // standard links
  165. if (RefLogUtils.getRefLogBranch(r) == null) {
  166. pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params));
  167. } else {
  168. pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params));
  169. // pages.put("overview", new PageRegistration("gb.overview", OverviewPage.class, params));
  170. pages.put("reflog", new PageRegistration("gb.reflog", ReflogPage.class, params));
  171. }
  172. pages.put("commits", new PageRegistration("gb.commits", LogPage.class, params));
  173. pages.put("tree", new PageRegistration("gb.tree", TreePage.class, params));
  174. pages.put("compare", new PageRegistration("gb.compare", ComparePage.class, params, true));
  175. if (GitBlit.getBoolean(Keys.web.allowForking, true)) {
  176. pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params, true));
  177. }
  178. // conditional links
  179. // per-repository extra page links
  180. if (model.useTickets && TicgitUtils.getTicketsBranch(r) != null) {
  181. pages.put("tickets", new PageRegistration("gb.tickets", TicketsPage.class, params, true));
  182. }
  183. if (model.showReadme || model.useDocs) {
  184. pages.put("docs", new PageRegistration("gb.docs", DocsPage.class, params, true));
  185. }
  186. if (JGitUtils.getPagesBranch(r) != null) {
  187. OtherPageLink pagesLink = new OtherPageLink("gb.pages", PagesServlet.asLink(
  188. getRequest().getRelativePathPrefixToContextRoot(), repositoryName, null), true);
  189. pages.put("pages", pagesLink);
  190. }
  191. // Conditionally add edit link
  192. showAdmin = false;
  193. if (GitBlit.getBoolean(Keys.web.authenticateAdminPages, true)) {
  194. boolean allowAdmin = GitBlit.getBoolean(Keys.web.allowAdministration, false);
  195. showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin();
  196. } else {
  197. showAdmin = GitBlit.getBoolean(Keys.web.allowAdministration, false);
  198. }
  199. isOwner = GitBlitWebSession.get().isLoggedIn()
  200. && (model.isOwner(GitBlitWebSession.get()
  201. .getUsername()));
  202. return pages;
  203. }
  204. protected boolean allowForkControls() {
  205. return GitBlit.getBoolean(Keys.web.allowForking, true);
  206. }
  207. @Override
  208. protected void setupPage(String repositoryName, String pageName) {
  209. String projectName = StringUtils.getFirstPathElement(repositoryName);
  210. ProjectModel project = GitBlit.self().getProjectModel(projectName);
  211. if (project.isUserProject()) {
  212. // user-as-project
  213. add(new LinkPanel("projectTitle", null, project.getDisplayName(),
  214. UserPage.class, WicketUtils.newUsernameParameter(project.name.substring(1))));
  215. } else {
  216. // project
  217. add(new LinkPanel("projectTitle", null, project.name,
  218. ProjectPage.class, WicketUtils.newProjectParameter(project.name)));
  219. }
  220. String name = StringUtils.stripDotGit(repositoryName);
  221. if (!StringUtils.isEmpty(projectName) && name.startsWith(projectName)) {
  222. name = name.substring(projectName.length() + 1);
  223. }
  224. add(new LinkPanel("repositoryName", null, name, SummaryPage.class,
  225. WicketUtils.newRepositoryParameter(repositoryName)));
  226. add(new Label("pageName", pageName).setRenderBodyOnly(true));
  227. UserModel user = GitBlitWebSession.get().getUser();
  228. if (user == null) {
  229. user = UserModel.ANONYMOUS;
  230. }
  231. // indicate origin repository
  232. RepositoryModel model = getRepositoryModel();
  233. if (StringUtils.isEmpty(model.originRepository)) {
  234. add(new Label("originRepository").setVisible(false));
  235. } else {
  236. RepositoryModel origin = GitBlit.self().getRepositoryModel(model.originRepository);
  237. if (origin == null) {
  238. // no origin repository
  239. add(new Label("originRepository").setVisible(false));
  240. } else if (!user.canView(origin)) {
  241. // show origin repository without link
  242. Fragment forkFrag = new Fragment("originRepository", "originFragment", this);
  243. forkFrag.add(new Label("originRepository", StringUtils.stripDotGit(model.originRepository)));
  244. add(forkFrag);
  245. } else {
  246. // link to origin repository
  247. Fragment forkFrag = new Fragment("originRepository", "originFragment", this);
  248. forkFrag.add(new LinkPanel("originRepository", null, StringUtils.stripDotGit(model.originRepository),
  249. SummaryPage.class, WicketUtils.newRepositoryParameter(model.originRepository)));
  250. add(forkFrag);
  251. }
  252. }
  253. // (un)star link allows a user to star a repository
  254. if (user.isAuthenticated) {
  255. PageParameters starParams = DeepCopier.copy(getPageParameters());
  256. starParams.put(PARAM_STAR, !user.getPreferences().isStarredRepository(model.name));
  257. String toggleStarUrl = getRequestCycle().urlFor(getClass(), starParams).toString();
  258. if (user.getPreferences().isStarredRepository(model.name)) {
  259. // show unstar button
  260. add(new Label("starLink").setVisible(false));
  261. addToolbarButton("unstarLink", "icon-star-empty", getString("gb.unstar"), toggleStarUrl);
  262. } else {
  263. // show star button
  264. addToolbarButton("starLink", "icon-star", getString("gb.star"), toggleStarUrl);
  265. add(new Label("unstarLink").setVisible(false));
  266. }
  267. } else {
  268. // anonymous user
  269. add(new Label("starLink").setVisible(false));
  270. add(new Label("unstarLink").setVisible(false));
  271. }
  272. // fork controls
  273. if (!allowForkControls() || user == null || !user.isAuthenticated) {
  274. // must be logged-in to fork, hide all fork controls
  275. add(new ExternalLink("forkLink", "").setVisible(false));
  276. add(new ExternalLink("myForkLink", "").setVisible(false));
  277. } else {
  278. String fork = GitBlit.self().getFork(user.username, model.name);
  279. boolean hasFork = fork != null;
  280. boolean canFork = user.canFork(model);
  281. if (hasFork || !canFork) {
  282. // user not allowed to fork or fork already exists or repo forbids forking
  283. add(new ExternalLink("forkLink", "").setVisible(false));
  284. if (hasFork && !fork.equals(model.name)) {
  285. // user has fork, view my fork link
  286. String url = getRequestCycle().urlFor(SummaryPage.class, WicketUtils.newRepositoryParameter(fork)).toString();
  287. add(new ExternalLink("myForkLink", url));
  288. } else {
  289. // no fork, hide view my fork link
  290. add(new ExternalLink("myForkLink", "").setVisible(false));
  291. }
  292. } else if (canFork) {
  293. // can fork and we do not have one
  294. add(new ExternalLink("myForkLink", "").setVisible(false));
  295. String url = getRequestCycle().urlFor(ForkPage.class, WicketUtils.newRepositoryParameter(model.name)).toString();
  296. add(new ExternalLink("forkLink", url));
  297. }
  298. }
  299. if (showAdmin || isOwner) {
  300. String url = getRequestCycle().urlFor(EditRepositoryPage.class, WicketUtils.newRepositoryParameter(model.name)).toString();
  301. add(new ExternalLink("editLink", url));
  302. } else {
  303. add(new Label("editLink").setVisible(false));
  304. }
  305. super.setupPage(repositoryName, pageName);
  306. }
  307. protected void addToolbarButton(String wicketId, String iconClass, String label, String url) {
  308. Fragment button = new Fragment(wicketId, "toolbarLinkFragment", this);
  309. Label icon = new Label("icon");
  310. WicketUtils.setCssClass(icon, iconClass);
  311. button.add(icon);
  312. button.add(new Label("label", label));
  313. button.add(new SimpleAttributeModifier("href", url));
  314. add(button);
  315. }
  316. protected void addSyndicationDiscoveryLink() {
  317. add(WicketUtils.syndicationDiscoveryLink(SyndicationServlet.getTitle(repositoryName,
  318. objectId), SyndicationServlet.asLink(getRequest()
  319. .getRelativePathPrefixToContextRoot(), repositoryName, objectId, 0)));
  320. }
  321. protected Repository getRepository() {
  322. if (r == null) {
  323. Repository r = GitBlit.self().getRepository(repositoryName);
  324. if (r == null) {
  325. error(getString("gb.canNotLoadRepository") + " " + repositoryName, true);
  326. return null;
  327. }
  328. this.r = r;
  329. }
  330. return r;
  331. }
  332. protected RepositoryModel getRepositoryModel() {
  333. if (m == null) {
  334. RepositoryModel model = GitBlit.self().getRepositoryModel(
  335. GitBlitWebSession.get().getUser(), repositoryName);
  336. if (model == null) {
  337. if (GitBlit.self().hasRepository(repositoryName, true)) {
  338. // has repository, but unauthorized
  339. authenticationError(getString("gb.unauthorizedAccessForRepository") + " " + repositoryName);
  340. } else {
  341. // does not have repository
  342. error(getString("gb.canNotLoadRepository") + " " + repositoryName, true);
  343. }
  344. return null;
  345. }
  346. m = model;
  347. }
  348. return m;
  349. }
  350. protected RevCommit getCommit() {
  351. RevCommit commit = JGitUtils.getCommit(r, objectId);
  352. if (commit == null) {
  353. error(MessageFormat.format(getString("gb.failedToFindCommit"),
  354. objectId, repositoryName, getPageName()), null, LogPage.class,
  355. WicketUtils.newRepositoryParameter(repositoryName));
  356. }
  357. getSubmodules(commit);
  358. return commit;
  359. }
  360. protected Map<String, SubmoduleModel> getSubmodules(RevCommit commit) {
  361. if (submodules == null) {
  362. submodules = new HashMap<String, SubmoduleModel>();
  363. for (SubmoduleModel model : JGitUtils.getSubmodules(r, commit.getTree())) {
  364. submodules.put(model.path, model);
  365. }
  366. }
  367. return submodules;
  368. }
  369. protected SubmoduleModel getSubmodule(String path) {
  370. SubmoduleModel model = null;
  371. if (submodules != null) {
  372. model = submodules.get(path);
  373. }
  374. if (model == null) {
  375. // undefined submodule?!
  376. model = new SubmoduleModel(path.substring(path.lastIndexOf('/') + 1), path, path);
  377. model.hasSubmodule = false;
  378. model.gitblitPath = model.name;
  379. return model;
  380. } else {
  381. // extract the repository name from the clone url
  382. List<String> patterns = GitBlit.getStrings(Keys.git.submoduleUrlPatterns);
  383. String submoduleName = StringUtils.extractRepositoryPath(model.url, patterns.toArray(new String[0]));
  384. // determine the current path for constructing paths relative
  385. // to the current repository
  386. String currentPath = "";
  387. if (repositoryName.indexOf('/') > -1) {
  388. currentPath = repositoryName.substring(0, repositoryName.lastIndexOf('/') + 1);
  389. }
  390. // try to locate the submodule repository
  391. // prefer bare to non-bare names
  392. List<String> candidates = new ArrayList<String>();
  393. // relative
  394. candidates.add(currentPath + StringUtils.stripDotGit(submoduleName));
  395. candidates.add(candidates.get(candidates.size() - 1) + ".git");
  396. // relative, no subfolder
  397. if (submoduleName.lastIndexOf('/') > -1) {
  398. String name = submoduleName.substring(submoduleName.lastIndexOf('/') + 1);
  399. candidates.add(currentPath + StringUtils.stripDotGit(name));
  400. candidates.add(candidates.get(candidates.size() - 1) + ".git");
  401. }
  402. // absolute
  403. candidates.add(StringUtils.stripDotGit(submoduleName));
  404. candidates.add(candidates.get(candidates.size() - 1) + ".git");
  405. // absolute, no subfolder
  406. if (submoduleName.lastIndexOf('/') > -1) {
  407. String name = submoduleName.substring(submoduleName.lastIndexOf('/') + 1);
  408. candidates.add(StringUtils.stripDotGit(name));
  409. candidates.add(candidates.get(candidates.size() - 1) + ".git");
  410. }
  411. // create a unique, ordered set of candidate paths
  412. Set<String> paths = new LinkedHashSet<String>(candidates);
  413. for (String candidate : paths) {
  414. if (GitBlit.self().hasRepository(candidate)) {
  415. model.hasSubmodule = true;
  416. model.gitblitPath = candidate;
  417. return model;
  418. }
  419. }
  420. // we do not have a copy of the submodule, but we need a path
  421. model.gitblitPath = candidates.get(0);
  422. return model;
  423. }
  424. }
  425. protected String getShortObjectId(String objectId) {
  426. return objectId.substring(0, GitBlit.getInteger(Keys.web.shortCommitIdLength, 6));
  427. }
  428. protected void addRefs(Repository r, RevCommit c) {
  429. add(new RefsPanel("refsPanel", repositoryName, c, JGitUtils.getAllRefs(r, getRepositoryModel().showRemoteBranches)));
  430. }
  431. protected void addFullText(String wicketId, String text, boolean substituteRegex) {
  432. String html = StringUtils.escapeForHtml(text, false);
  433. if (substituteRegex) {
  434. html = GitBlit.self().processCommitMessage(repositoryName, html);
  435. } else {
  436. html = StringUtils.breakLinesForHtml(html);
  437. }
  438. add(new Label(wicketId, html).setEscapeModelStrings(false));
  439. }
  440. protected abstract String getPageName();
  441. protected Component createPersonPanel(String wicketId, PersonIdent identity,
  442. Constants.SearchType searchType) {
  443. String name = identity == null ? "" : identity.getName();
  444. String address = identity == null ? "" : identity.getEmailAddress();
  445. name = StringUtils.removeNewlines(name);
  446. address = StringUtils.removeNewlines(address);
  447. boolean showEmail = GitBlit.getBoolean(Keys.web.showEmailAddresses, false);
  448. if (!showEmail || StringUtils.isEmpty(name) || StringUtils.isEmpty(address)) {
  449. String value = name;
  450. if (StringUtils.isEmpty(value)) {
  451. if (showEmail) {
  452. value = address;
  453. } else {
  454. value = getString("gb.missingUsername");
  455. }
  456. }
  457. Fragment partial = new Fragment(wicketId, "partialPersonIdent", this);
  458. LinkPanel link = new LinkPanel("personName", "list", value, GitSearchPage.class,
  459. WicketUtils.newSearchParameter(repositoryName, objectId, value, searchType));
  460. setPersonSearchTooltip(link, value, searchType);
  461. partial.add(link);
  462. return partial;
  463. } else {
  464. Fragment fullPerson = new Fragment(wicketId, "fullPersonIdent", this);
  465. LinkPanel nameLink = new LinkPanel("personName", "list", name, GitSearchPage.class,
  466. WicketUtils.newSearchParameter(repositoryName, objectId, name, searchType));
  467. setPersonSearchTooltip(nameLink, name, searchType);
  468. fullPerson.add(nameLink);
  469. LinkPanel addressLink = new LinkPanel("personAddress", "hidden-phone list", "<" + address + ">",
  470. GitSearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId,
  471. address, searchType));
  472. setPersonSearchTooltip(addressLink, address, searchType);
  473. fullPerson.add(addressLink);
  474. return fullPerson;
  475. }
  476. }
  477. protected void setPersonSearchTooltip(Component component, String value,
  478. Constants.SearchType searchType) {
  479. if (searchType.equals(Constants.SearchType.AUTHOR)) {
  480. WicketUtils.setHtmlTooltip(component, getString("gb.searchForAuthor") + " " + value);
  481. } else if (searchType.equals(Constants.SearchType.COMMITTER)) {
  482. WicketUtils.setHtmlTooltip(component, getString("gb.searchForCommitter") + " " + value);
  483. }
  484. }
  485. protected void setChangeTypeTooltip(Component container, ChangeType type) {
  486. switch (type) {
  487. case ADD:
  488. WicketUtils.setHtmlTooltip(container, getString("gb.addition"));
  489. break;
  490. case COPY:
  491. case RENAME:
  492. WicketUtils.setHtmlTooltip(container, getString("gb.rename"));
  493. break;
  494. case DELETE:
  495. WicketUtils.setHtmlTooltip(container, getString("gb.deletion"));
  496. break;
  497. case MODIFY:
  498. WicketUtils.setHtmlTooltip(container, getString("gb.modification"));
  499. break;
  500. }
  501. }
  502. @Override
  503. protected void onBeforeRender() {
  504. // dispose of repository object
  505. if (r != null) {
  506. r.close();
  507. r = null;
  508. }
  509. // setup page header and footer
  510. setupPage(repositoryName, "/ " + getPageName());
  511. super.onBeforeRender();
  512. }
  513. @Override
  514. protected void setLastModified() {
  515. if (getClass().isAnnotationPresent(CacheControl.class)) {
  516. CacheControl cacheControl = getClass().getAnnotation(CacheControl.class);
  517. switch (cacheControl.value()) {
  518. case REPOSITORY:
  519. RepositoryModel repository = getRepositoryModel();
  520. if (repository != null) {
  521. setLastModified(repository.lastChange);
  522. }
  523. break;
  524. case COMMIT:
  525. RevCommit commit = getCommit();
  526. if (commit != null) {
  527. Date commitDate = JGitUtils.getCommitDate(commit);
  528. setLastModified(commitDate);
  529. }
  530. break;
  531. default:
  532. super.setLastModified();
  533. }
  534. }
  535. }
  536. protected PageParameters newRepositoryParameter() {
  537. return WicketUtils.newRepositoryParameter(repositoryName);
  538. }
  539. protected PageParameters newCommitParameter() {
  540. return WicketUtils.newObjectParameter(repositoryName, objectId);
  541. }
  542. protected PageParameters newCommitParameter(String commitId) {
  543. return WicketUtils.newObjectParameter(repositoryName, commitId);
  544. }
  545. public boolean isShowAdmin() {
  546. return showAdmin;
  547. }
  548. public boolean isOwner() {
  549. return isOwner;
  550. }
  551. private class SearchForm extends SessionlessForm<Void> implements Serializable {
  552. private static final long serialVersionUID = 1L;
  553. private final String repositoryName;
  554. private final IModel<String> searchBoxModel = new Model<String>("");
  555. private final IModel<Constants.SearchType> searchTypeModel = new Model<Constants.SearchType>(
  556. Constants.SearchType.COMMIT);
  557. public SearchForm(String id, String repositoryName) {
  558. super(id, RepositoryPage.this.getClass(), RepositoryPage.this.getPageParameters());
  559. this.repositoryName = repositoryName;
  560. DropDownChoice<Constants.SearchType> searchType = new DropDownChoice<Constants.SearchType>(
  561. "searchType", Arrays.asList(Constants.SearchType.values()));
  562. searchType.setModel(searchTypeModel);
  563. add(searchType.setVisible(GitBlit.getBoolean(Keys.web.showSearchTypeSelection, false)));
  564. TextField<String> searchBox = new TextField<String>("searchBox", searchBoxModel);
  565. add(searchBox);
  566. }
  567. void setTranslatedAttributes() {
  568. WicketUtils.setHtmlTooltip(get("searchType"), getString("gb.searchTypeTooltip"));
  569. WicketUtils.setHtmlTooltip(get("searchBox"),
  570. MessageFormat.format(getString("gb.searchTooltip"), repositoryName));
  571. WicketUtils.setInputPlaceholder(get("searchBox"), getString("gb.search"));
  572. }
  573. @Override
  574. public void onSubmit() {
  575. Constants.SearchType searchType = searchTypeModel.getObject();
  576. String searchString = searchBoxModel.getObject();
  577. if (StringUtils.isEmpty(searchString)) {
  578. // redirect to self to avoid wicket page update bug
  579. PageParameters params = RepositoryPage.this.getPageParameters();
  580. String relativeUrl = urlFor(RepositoryPage.this.getClass(), params).toString();
  581. String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl);
  582. getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
  583. return;
  584. }
  585. for (Constants.SearchType type : Constants.SearchType.values()) {
  586. if (searchString.toLowerCase().startsWith(type.name().toLowerCase() + ":")) {
  587. searchType = type;
  588. searchString = searchString.substring(type.name().toLowerCase().length() + 1)
  589. .trim();
  590. break;
  591. }
  592. }
  593. Class<? extends BasePage> searchPageClass = GitSearchPage.class;
  594. RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
  595. if (GitBlit.getBoolean(Keys.web.allowLuceneIndexing, true)
  596. && !ArrayUtils.isEmpty(model.indexedBranches)) {
  597. // this repository is Lucene-indexed
  598. searchPageClass = LuceneSearchPage.class;
  599. }
  600. // use an absolute url to workaround Wicket-Tomcat problems with
  601. // mounted url parameters (issue-111)
  602. PageParameters params = WicketUtils.newSearchParameter(repositoryName, null, searchString, searchType);
  603. String relativeUrl = urlFor(searchPageClass, params).toString();
  604. String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl);
  605. getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
  606. }
  607. }
  608. }