Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

13 роки тому
12 роки тому
12 роки тому
12 роки тому
12 роки тому
13 роки тому
13 роки тому
12 роки тому
13 роки тому
13 роки тому
11 роки тому
13 роки тому
11 роки тому
11 роки тому
13 роки тому
13 роки тому
13 роки тому
12 роки тому
13 роки тому
12 роки тому
12 роки тому
12 роки тому
12 роки тому
12 роки тому
12 роки тому
12 роки тому
13 роки тому
13 роки тому
13 роки тому
13 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  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.request.target.basic.RedirectRequestTarget;
  39. import org.eclipse.jgit.diff.DiffEntry.ChangeType;
  40. import org.eclipse.jgit.lib.PersonIdent;
  41. import org.eclipse.jgit.lib.Repository;
  42. import org.eclipse.jgit.revwalk.RevCommit;
  43. import org.slf4j.Logger;
  44. import org.slf4j.LoggerFactory;
  45. import com.gitblit.Constants;
  46. import com.gitblit.GitBlit;
  47. import com.gitblit.GitBlitException;
  48. import com.gitblit.Keys;
  49. import com.gitblit.PagesServlet;
  50. import com.gitblit.SyndicationServlet;
  51. import com.gitblit.models.ProjectModel;
  52. import com.gitblit.models.RefModel;
  53. import com.gitblit.models.RepositoryModel;
  54. import com.gitblit.models.SubmoduleModel;
  55. import com.gitblit.models.UserModel;
  56. import com.gitblit.models.UserRepositoryPreferences;
  57. import com.gitblit.utils.ArrayUtils;
  58. import com.gitblit.utils.DeepCopier;
  59. import com.gitblit.utils.JGitUtils;
  60. import com.gitblit.utils.RefLogUtils;
  61. import com.gitblit.utils.StringUtils;
  62. import com.gitblit.wicket.CacheControl;
  63. import com.gitblit.wicket.GitBlitWebSession;
  64. import com.gitblit.wicket.PageRegistration;
  65. import com.gitblit.wicket.PageRegistration.OtherPageLink;
  66. import com.gitblit.wicket.SessionlessForm;
  67. import com.gitblit.wicket.WicketUtils;
  68. import com.gitblit.wicket.panels.LinkPanel;
  69. import com.gitblit.wicket.panels.NavigationPanel;
  70. import com.gitblit.wicket.panels.RefsPanel;
  71. public abstract class RepositoryPage extends RootPage {
  72. protected final Logger logger = LoggerFactory.getLogger(getClass());
  73. private final String PARAM_STAR = "star";
  74. protected final String projectName;
  75. protected final String repositoryName;
  76. protected final String objectId;
  77. private transient Repository r;
  78. private RepositoryModel m;
  79. private Map<String, SubmoduleModel> submodules;
  80. private final Map<String, PageRegistration> registeredPages;
  81. private boolean showAdmin;
  82. private boolean isOwner;
  83. public RepositoryPage(PageParameters params) {
  84. super(params);
  85. repositoryName = WicketUtils.getRepositoryName(params);
  86. String root =StringUtils.getFirstPathElement(repositoryName);
  87. if (StringUtils.isEmpty(root)) {
  88. projectName = GitBlit.getString(Keys.web.repositoryRootGroupName, "main");
  89. } else {
  90. projectName = root;
  91. }
  92. objectId = WicketUtils.getObject(params);
  93. if (StringUtils.isEmpty(repositoryName)) {
  94. error(MessageFormat.format(getString("gb.repositoryNotSpecifiedFor"), getPageName()), true);
  95. }
  96. if (!getRepositoryModel().hasCommits) {
  97. setResponsePage(EmptyRepositoryPage.class, params);
  98. }
  99. if (getRepositoryModel().isCollectingGarbage) {
  100. error(MessageFormat.format(getString("gb.busyCollectingGarbage"), getRepositoryModel().name), true);
  101. }
  102. if (objectId != null) {
  103. RefModel branch = null;
  104. if ((branch = JGitUtils.getBranch(getRepository(), objectId)) != null) {
  105. UserModel user = GitBlitWebSession.get().getUser();
  106. if (user == null) {
  107. // workaround until get().getUser() is reviewed throughout the app
  108. user = UserModel.ANONYMOUS;
  109. }
  110. boolean canAccess = user.canView(getRepositoryModel(),
  111. branch.reference.getName());
  112. if (!canAccess) {
  113. error(getString("gb.accessDenied"), true);
  114. }
  115. }
  116. }
  117. if (params.containsKey(PARAM_STAR)) {
  118. // set starred state
  119. boolean star = params.getBoolean(PARAM_STAR);
  120. UserModel user = GitBlitWebSession.get().getUser();
  121. if (user != null && user.isAuthenticated) {
  122. UserRepositoryPreferences prefs = user.getPreferences().getRepositoryPreferences(getRepositoryModel().name);
  123. prefs.starred = star;
  124. try {
  125. GitBlit.self().updateUserModel(user.username, user, false);
  126. } catch (GitBlitException e) {
  127. logger.error("Failed to update user " + user.username, e);
  128. error(getString("gb.failedToUpdateUser"), false);
  129. }
  130. }
  131. }
  132. // register the available page links for this page and user
  133. registeredPages = registerPages();
  134. // standard page links
  135. List<PageRegistration> pages = new ArrayList<PageRegistration>(registeredPages.values());
  136. NavigationPanel navigationPanel = new NavigationPanel("repositoryNavPanel", getRepoNavPageClass(), pages);
  137. add(navigationPanel);
  138. add(new ExternalLink("syndication", SyndicationServlet.asLink(getRequest()
  139. .getRelativePathPrefixToContextRoot(), repositoryName, null, 0)));
  140. // add floating search form
  141. SearchForm searchForm = new SearchForm("searchForm", repositoryName);
  142. add(searchForm);
  143. searchForm.setTranslatedAttributes();
  144. // set stateless page preference
  145. setStatelessHint(true);
  146. }
  147. @Override
  148. protected Class<? extends BasePage> getRootNavPageClass() {
  149. return RepositoriesPage.class;
  150. }
  151. protected Class<? extends BasePage> getRepoNavPageClass() {
  152. return getClass();
  153. }
  154. private Map<String, PageRegistration> registerPages() {
  155. PageParameters params = null;
  156. if (!StringUtils.isEmpty(repositoryName)) {
  157. params = WicketUtils.newRepositoryParameter(repositoryName);
  158. }
  159. Map<String, PageRegistration> pages = new LinkedHashMap<String, PageRegistration>();
  160. Repository r = getRepository();
  161. RepositoryModel model = getRepositoryModel();
  162. // standard links
  163. if (RefLogUtils.getRefLogBranch(r) == null) {
  164. pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params));
  165. } else {
  166. pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params));
  167. // pages.put("overview", new PageRegistration("gb.overview", OverviewPage.class, params));
  168. pages.put("reflog", new PageRegistration("gb.reflog", ReflogPage.class, params));
  169. }
  170. pages.put("commits", new PageRegistration("gb.commits", LogPage.class, params));
  171. pages.put("tree", new PageRegistration("gb.tree", TreePage.class, params));
  172. pages.put("docs", new PageRegistration("gb.docs", DocsPage.class, params, true));
  173. pages.put("compare", new PageRegistration("gb.compare", ComparePage.class, params, true));
  174. if (GitBlit.getBoolean(Keys.web.allowForking, true)) {
  175. pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params, true));
  176. }
  177. // conditional links
  178. // per-repository extra page links
  179. if (JGitUtils.getPagesBranch(r) != null) {
  180. OtherPageLink pagesLink = new OtherPageLink("gb.pages", PagesServlet.asLink(
  181. getRequest().getRelativePathPrefixToContextRoot(), repositoryName, null), true);
  182. pages.put("pages", pagesLink);
  183. }
  184. // Conditionally add edit link
  185. showAdmin = false;
  186. if (GitBlit.getBoolean(Keys.web.authenticateAdminPages, true)) {
  187. boolean allowAdmin = GitBlit.getBoolean(Keys.web.allowAdministration, false);
  188. showAdmin = allowAdmin && GitBlitWebSession.get().canAdmin();
  189. } else {
  190. showAdmin = GitBlit.getBoolean(Keys.web.allowAdministration, false);
  191. }
  192. isOwner = GitBlitWebSession.get().isLoggedIn()
  193. && (model.isOwner(GitBlitWebSession.get()
  194. .getUsername()));
  195. return pages;
  196. }
  197. protected boolean allowForkControls() {
  198. return GitBlit.getBoolean(Keys.web.allowForking, true);
  199. }
  200. @Override
  201. protected void setupPage(String repositoryName, String pageName) {
  202. String projectName = StringUtils.getFirstPathElement(repositoryName);
  203. ProjectModel project = GitBlit.self().getProjectModel(projectName);
  204. if (project.isUserProject()) {
  205. // user-as-project
  206. add(new LinkPanel("projectTitle", null, project.getDisplayName(),
  207. UserPage.class, WicketUtils.newUsernameParameter(project.name.substring(1))));
  208. } else {
  209. // project
  210. add(new LinkPanel("projectTitle", null, project.name,
  211. ProjectPage.class, WicketUtils.newProjectParameter(project.name)));
  212. }
  213. String name = StringUtils.stripDotGit(repositoryName);
  214. if (!StringUtils.isEmpty(projectName) && name.startsWith(projectName)) {
  215. name = name.substring(projectName.length() + 1);
  216. }
  217. add(new LinkPanel("repositoryName", null, name, SummaryPage.class,
  218. WicketUtils.newRepositoryParameter(repositoryName)));
  219. add(new Label("pageName", pageName).setRenderBodyOnly(true));
  220. UserModel user = GitBlitWebSession.get().getUser();
  221. if (user == null) {
  222. user = UserModel.ANONYMOUS;
  223. }
  224. // indicate origin repository
  225. RepositoryModel model = getRepositoryModel();
  226. if (StringUtils.isEmpty(model.originRepository)) {
  227. if (model.isMirror) {
  228. Fragment mirrorFrag = new Fragment("originRepository", "mirrorFragment", this);
  229. Label lbl = new Label("originRepository", MessageFormat.format(getString("gb.mirrorOf"), "<b>" + model.origin + "</b>"));
  230. mirrorFrag.add(lbl.setEscapeModelStrings(false));
  231. add(mirrorFrag);
  232. } else {
  233. add(new Label("originRepository").setVisible(false));
  234. }
  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 String getBestCommitId(RevCommit commit) {
  361. String head = null;
  362. try {
  363. head = r.resolve(getRepositoryModel().HEAD).getName();
  364. } catch (Exception e) {
  365. }
  366. String id = commit.getName();
  367. if (!StringUtils.isEmpty(head) && head.equals(id)) {
  368. // match default branch
  369. return Repository.shortenRefName(getRepositoryModel().HEAD);
  370. }
  371. // find first branch match
  372. for (RefModel ref : JGitUtils.getLocalBranches(r, false, -1)) {
  373. if (ref.getObjectId().getName().equals(id)) {
  374. return ref.getName();
  375. }
  376. }
  377. // return sha
  378. return id;
  379. }
  380. protected Map<String, SubmoduleModel> getSubmodules(RevCommit commit) {
  381. if (submodules == null) {
  382. submodules = new HashMap<String, SubmoduleModel>();
  383. for (SubmoduleModel model : JGitUtils.getSubmodules(r, commit.getTree())) {
  384. submodules.put(model.path, model);
  385. }
  386. }
  387. return submodules;
  388. }
  389. protected SubmoduleModel getSubmodule(String path) {
  390. SubmoduleModel model = null;
  391. if (submodules != null) {
  392. model = submodules.get(path);
  393. }
  394. if (model == null) {
  395. // undefined submodule?!
  396. model = new SubmoduleModel(path.substring(path.lastIndexOf('/') + 1), path, path);
  397. model.hasSubmodule = false;
  398. model.gitblitPath = model.name;
  399. return model;
  400. } else {
  401. // extract the repository name from the clone url
  402. List<String> patterns = GitBlit.getStrings(Keys.git.submoduleUrlPatterns);
  403. String submoduleName = StringUtils.extractRepositoryPath(model.url, patterns.toArray(new String[0]));
  404. // determine the current path for constructing paths relative
  405. // to the current repository
  406. String currentPath = "";
  407. if (repositoryName.indexOf('/') > -1) {
  408. currentPath = repositoryName.substring(0, repositoryName.lastIndexOf('/') + 1);
  409. }
  410. // try to locate the submodule repository
  411. // prefer bare to non-bare names
  412. List<String> candidates = new ArrayList<String>();
  413. // relative
  414. candidates.add(currentPath + StringUtils.stripDotGit(submoduleName));
  415. candidates.add(candidates.get(candidates.size() - 1) + ".git");
  416. // relative, no subfolder
  417. if (submoduleName.lastIndexOf('/') > -1) {
  418. String name = submoduleName.substring(submoduleName.lastIndexOf('/') + 1);
  419. candidates.add(currentPath + StringUtils.stripDotGit(name));
  420. candidates.add(candidates.get(candidates.size() - 1) + ".git");
  421. }
  422. // absolute
  423. candidates.add(StringUtils.stripDotGit(submoduleName));
  424. candidates.add(candidates.get(candidates.size() - 1) + ".git");
  425. // absolute, no subfolder
  426. if (submoduleName.lastIndexOf('/') > -1) {
  427. String name = submoduleName.substring(submoduleName.lastIndexOf('/') + 1);
  428. candidates.add(StringUtils.stripDotGit(name));
  429. candidates.add(candidates.get(candidates.size() - 1) + ".git");
  430. }
  431. // create a unique, ordered set of candidate paths
  432. Set<String> paths = new LinkedHashSet<String>(candidates);
  433. for (String candidate : paths) {
  434. if (GitBlit.self().hasRepository(candidate)) {
  435. model.hasSubmodule = true;
  436. model.gitblitPath = candidate;
  437. return model;
  438. }
  439. }
  440. // we do not have a copy of the submodule, but we need a path
  441. model.gitblitPath = candidates.get(0);
  442. return model;
  443. }
  444. }
  445. protected String getShortObjectId(String objectId) {
  446. return objectId.substring(0, GitBlit.getInteger(Keys.web.shortCommitIdLength, 6));
  447. }
  448. protected void addRefs(Repository r, RevCommit c) {
  449. add(new RefsPanel("refsPanel", repositoryName, c, JGitUtils.getAllRefs(r, getRepositoryModel().showRemoteBranches)));
  450. }
  451. protected void addFullText(String wicketId, String text) {
  452. RepositoryModel model = getRepositoryModel();
  453. String content = GitBlit.self().processCommitMessage(model, text);
  454. String html;
  455. switch (model.commitMessageRenderer) {
  456. case MARKDOWN:
  457. html = MessageFormat.format("<div class='commit_message'>{0}</div>", content);
  458. break;
  459. default:
  460. html = MessageFormat.format("<pre class='commit_message'>{0}</pre>", content);
  461. break;
  462. }
  463. add(new Label(wicketId, html).setEscapeModelStrings(false));
  464. }
  465. protected abstract String getPageName();
  466. protected Component createPersonPanel(String wicketId, PersonIdent identity,
  467. Constants.SearchType searchType) {
  468. String name = identity == null ? "" : identity.getName();
  469. String address = identity == null ? "" : identity.getEmailAddress();
  470. name = StringUtils.removeNewlines(name);
  471. address = StringUtils.removeNewlines(address);
  472. boolean showEmail = GitBlit.getBoolean(Keys.web.showEmailAddresses, false);
  473. if (!showEmail || StringUtils.isEmpty(name) || StringUtils.isEmpty(address)) {
  474. String value = name;
  475. if (StringUtils.isEmpty(value)) {
  476. if (showEmail) {
  477. value = address;
  478. } else {
  479. value = getString("gb.missingUsername");
  480. }
  481. }
  482. Fragment partial = new Fragment(wicketId, "partialPersonIdent", this);
  483. LinkPanel link = new LinkPanel("personName", "list", value, GitSearchPage.class,
  484. WicketUtils.newSearchParameter(repositoryName, objectId, value, searchType));
  485. setPersonSearchTooltip(link, value, searchType);
  486. partial.add(link);
  487. return partial;
  488. } else {
  489. Fragment fullPerson = new Fragment(wicketId, "fullPersonIdent", this);
  490. LinkPanel nameLink = new LinkPanel("personName", "list", name, GitSearchPage.class,
  491. WicketUtils.newSearchParameter(repositoryName, objectId, name, searchType));
  492. setPersonSearchTooltip(nameLink, name, searchType);
  493. fullPerson.add(nameLink);
  494. LinkPanel addressLink = new LinkPanel("personAddress", "hidden-phone list", "<" + address + ">",
  495. GitSearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId,
  496. address, searchType));
  497. setPersonSearchTooltip(addressLink, address, searchType);
  498. fullPerson.add(addressLink);
  499. return fullPerson;
  500. }
  501. }
  502. protected void setPersonSearchTooltip(Component component, String value,
  503. Constants.SearchType searchType) {
  504. if (searchType.equals(Constants.SearchType.AUTHOR)) {
  505. WicketUtils.setHtmlTooltip(component, getString("gb.searchForAuthor") + " " + value);
  506. } else if (searchType.equals(Constants.SearchType.COMMITTER)) {
  507. WicketUtils.setHtmlTooltip(component, getString("gb.searchForCommitter") + " " + value);
  508. }
  509. }
  510. protected void setChangeTypeTooltip(Component container, ChangeType type) {
  511. switch (type) {
  512. case ADD:
  513. WicketUtils.setHtmlTooltip(container, getString("gb.addition"));
  514. break;
  515. case COPY:
  516. case RENAME:
  517. WicketUtils.setHtmlTooltip(container, getString("gb.rename"));
  518. break;
  519. case DELETE:
  520. WicketUtils.setHtmlTooltip(container, getString("gb.deletion"));
  521. break;
  522. case MODIFY:
  523. WicketUtils.setHtmlTooltip(container, getString("gb.modification"));
  524. break;
  525. }
  526. }
  527. @Override
  528. protected void onBeforeRender() {
  529. // dispose of repository object
  530. if (r != null) {
  531. r.close();
  532. r = null;
  533. }
  534. // setup page header and footer
  535. setupPage(repositoryName, "/ " + getPageName());
  536. super.onBeforeRender();
  537. }
  538. @Override
  539. protected void setLastModified() {
  540. if (getClass().isAnnotationPresent(CacheControl.class)) {
  541. CacheControl cacheControl = getClass().getAnnotation(CacheControl.class);
  542. switch (cacheControl.value()) {
  543. case REPOSITORY:
  544. RepositoryModel repository = getRepositoryModel();
  545. if (repository != null) {
  546. setLastModified(repository.lastChange);
  547. }
  548. break;
  549. case COMMIT:
  550. RevCommit commit = getCommit();
  551. if (commit != null) {
  552. Date commitDate = JGitUtils.getCommitDate(commit);
  553. setLastModified(commitDate);
  554. }
  555. break;
  556. default:
  557. super.setLastModified();
  558. }
  559. }
  560. }
  561. protected PageParameters newRepositoryParameter() {
  562. return WicketUtils.newRepositoryParameter(repositoryName);
  563. }
  564. protected PageParameters newCommitParameter() {
  565. return WicketUtils.newObjectParameter(repositoryName, objectId);
  566. }
  567. protected PageParameters newCommitParameter(String commitId) {
  568. return WicketUtils.newObjectParameter(repositoryName, commitId);
  569. }
  570. public boolean isShowAdmin() {
  571. return showAdmin;
  572. }
  573. public boolean isOwner() {
  574. return isOwner;
  575. }
  576. private class SearchForm extends SessionlessForm<Void> implements Serializable {
  577. private static final long serialVersionUID = 1L;
  578. private final String repositoryName;
  579. private final IModel<String> searchBoxModel = new Model<String>("");
  580. private final IModel<Constants.SearchType> searchTypeModel = new Model<Constants.SearchType>(
  581. Constants.SearchType.COMMIT);
  582. public SearchForm(String id, String repositoryName) {
  583. super(id, RepositoryPage.this.getClass(), RepositoryPage.this.getPageParameters());
  584. this.repositoryName = repositoryName;
  585. DropDownChoice<Constants.SearchType> searchType = new DropDownChoice<Constants.SearchType>(
  586. "searchType", Arrays.asList(Constants.SearchType.values()));
  587. searchType.setModel(searchTypeModel);
  588. add(searchType.setVisible(GitBlit.getBoolean(Keys.web.showSearchTypeSelection, false)));
  589. TextField<String> searchBox = new TextField<String>("searchBox", searchBoxModel);
  590. add(searchBox);
  591. }
  592. void setTranslatedAttributes() {
  593. WicketUtils.setHtmlTooltip(get("searchType"), getString("gb.searchTypeTooltip"));
  594. WicketUtils.setHtmlTooltip(get("searchBox"),
  595. MessageFormat.format(getString("gb.searchTooltip"), repositoryName));
  596. WicketUtils.setInputPlaceholder(get("searchBox"), getString("gb.search"));
  597. }
  598. @Override
  599. public void onSubmit() {
  600. Constants.SearchType searchType = searchTypeModel.getObject();
  601. String searchString = searchBoxModel.getObject();
  602. if (StringUtils.isEmpty(searchString)) {
  603. // redirect to self to avoid wicket page update bug
  604. String absoluteUrl = getCanonicalUrl();
  605. getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
  606. return;
  607. }
  608. for (Constants.SearchType type : Constants.SearchType.values()) {
  609. if (searchString.toLowerCase().startsWith(type.name().toLowerCase() + ":")) {
  610. searchType = type;
  611. searchString = searchString.substring(type.name().toLowerCase().length() + 1)
  612. .trim();
  613. break;
  614. }
  615. }
  616. Class<? extends BasePage> searchPageClass = GitSearchPage.class;
  617. RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
  618. if (GitBlit.getBoolean(Keys.web.allowLuceneIndexing, true)
  619. && !ArrayUtils.isEmpty(model.indexedBranches)) {
  620. // this repository is Lucene-indexed
  621. searchPageClass = LuceneSearchPage.class;
  622. }
  623. // use an absolute url to workaround Wicket-Tomcat problems with
  624. // mounted url parameters (issue-111)
  625. PageParameters params = WicketUtils.newSearchParameter(repositoryName, null, searchString, searchType);
  626. String absoluteUrl = getCanonicalUrl(searchPageClass, params);
  627. getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
  628. }
  629. }
  630. }