PageController { @RequestMapping(value="/cherryPick/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}", method=RequestMethod.POST) @PreAuthorize("hasPagePermission(#projectName, #branchName, #path, VIEW)") public String cherryPick(@PathVariable String projectName, @PathVariable String branchName, @PathVariable String path, @RequestParam String version1, @RequestParam String version2, @RequestParam("branch") Set<String> targetBranches, @RequestParam boolean dryRun, WebRequest request, Model model, Authentication authentication, Locale locale) throws IOException { path = Util.toRealPagePath(path); for (String targetBranch : targetBranches) { if (!permissionEvaluator.hasPagePermission( authentication, projectName, targetBranch, path, Permission.EDIT_PAGE)) { return ErrorController.forbidden(); } } List<String> commits = cherryPicker.getCommitsList(projectName, branchName, path, version1, version2); if (commits.isEmpty()) { throw new IllegalArgumentException("no commits to cherry-pick"); } User user = userStore.getUser(authentication.getName()); Map<String, String[]> params = request.getParameterMap(); Set<CommitCherryPickConflictResolve> resolves = Sets.newHashSet(); for (Map.Entry<String, String[]> entry : params.entrySet()) { String name = entry.getKey(); if (name.startsWith("resolveText_")) { String branchCommit = StringUtils.substringAfter(name, "_"); String branch = StringUtils.substringBefore(branchCommit, "/"); String commit = StringUtils.substringAfter(branchCommit, "/"); String text = entry.getValue()[0]; CommitCherryPickConflictResolve resolve = new CommitCherryPickConflictResolve(branch, commit, text); resolves.add(resolve); } } Map<String, List<CommitCherryPickResult>> results = cherryPicker.cherryPick( projectName, branchName, path, commits, targetBranches, resolves, dryRun, user, locale); if (results.keySet().size() != targetBranches.size()) { throw new IllegalStateException(); } if (!dryRun) { boolean allOk = true; loop: for (List<CommitCherryPickResult> branchResults : results.values()) { for (CommitCherryPickResult result : branchResults) { if (result.getStatus() != CommitCherryPickResult.Status.OK) { allOk = false; break loop; } } } if (allOk) { return "redirect:/page/" + projectName + "/" + branchName + "/" + Util.toUrlPagePath(path); } } model.addAttribute("cherryPickResults", results); model.addAttribute("version1", version1); model.addAttribute("version2", version2); model.addAttribute("resolves", resolves); return "/project/branch/page/cherryPick"; }  @RequestMapping(value="/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}", method={ RequestMethod.GET, RequestMethod.HEAD }) @PreAuthorize("hasPagePermission(#projectName, #branchName, #path, VIEW)") String getPage(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, Model model, HttpServletRequest request, HttpServletResponse response); @RequestMapping(value="/create/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{parentPagePath:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}", method=RequestMethod.GET) @PreAuthorize("hasBranchPermission(#projectName, #branchName, EDIT_PAGE)") String createPage(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String parentPagePath, Model model); @RequestMapping(value="/edit/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}", method=RequestMethod.GET) @PreAuthorize("hasPagePermission(#projectName, #branchName, #path, EDIT_PAGE)") String editPage(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, Model model, HttpSession session); @RequestMapping(value="/save/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}", method=RequestMethod.POST) @PreAuthorize("hasBranchPermission(#form.projectName, #form.branchName, EDIT_PAGE)") String savePage(@ModelAttribute @Valid PageForm form, BindingResult bindingResult,
			Model model, Authentication authentication); @ModelAttribute PageForm createPageForm(@PathVariable String projectName, @PathVariable String branchName,
			@RequestParam(required=false) String path, @RequestParam(required=false) String parentPagePath,
			@RequestParam(required=false) String title, @RequestParam(required=false) String text,
			@RequestParam(required=false) String viewRestrictionRole,
			@RequestParam(required=false) String commit,
			@RequestParam(required=false) String[] tags,
			@RequestParam(required=false) Integer orderIndex); @RequestMapping(value="/generateName/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{parentPagePath:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}/json", method=RequestMethod.POST, produces="application/json") @ResponseBody @PreAuthorize("hasBranchPermission(#projectName, #branchName, VIEW)") Map<String, Object> generateName(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String parentPagePath, @RequestParam String title); @RequestMapping(value="/markdownToHtml/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/json", method=RequestMethod.POST, produces="application/json") @ResponseBody @PreAuthorize("isAuthenticated()") Map<String, String> markdownToHtml(@PathVariable String projectName, @PathVariable String branchName,
			@RequestParam String markdown, @RequestParam(required=false) String pagePath, Authentication authentication,
			Locale locale, HttpServletRequest request); @RequestMapping(value="/copyToBranch/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}", method=RequestMethod.POST) @PreAuthorize("hasPagePermission(#projectName, #branchName, #path, VIEW) and " + "hasBranchPermission(#projectName, #targetBranchName, EDIT_PAGE)") String copyToBranch(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, @RequestParam String targetBranchName, Authentication authentication); @RequestMapping(value="/delete/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}", method=RequestMethod.GET) @PreAuthorize("hasBranchPermission(#projectName, #branchName, EDIT_PAGE)") String deletePage(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, Authentication authentication); @RequestMapping(value="/relocate/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}", method=RequestMethod.POST) @PreAuthorize("hasBranchPermission(#projectName, #branchName, EDIT_PAGE)") String relocatePage(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, @RequestParam String newParentPagePath, Authentication authentication); @RequestMapping(value="/markdown/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}/json", method=RequestMethod.GET) @ResponseBody @PreAuthorize("hasPagePermission(#projectName, #branchName, #path, VIEW)") Map<String, String> getPageMarkdown(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, @RequestParam Set<String> versions); @RequestMapping(value="/markdownInRange/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}/" + "{rangeStart:[0-9]+},{rangeEnd:[0-9]+}/{commit:[0-9a-fA-F]+}/json", method=RequestMethod.GET) @ResponseBody @PreAuthorize("hasPagePermission(#projectName, #branchName, #path, VIEW)") Map<String, String> getPageMarkdownInRange(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, @PathVariable int rangeStart, @PathVariable int rangeEnd,
			@PathVariable String commit); @RequestMapping(value="/changes/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}", method=RequestMethod.GET) @PreAuthorize("isAuthenticated() and hasPagePermission(#projectName, #branchName, #path, VIEW)") String getPageChanges(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, Model model); @RequestMapping(value="/saveRange/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}/json", method=RequestMethod.POST) @ResponseBody @PreAuthorize("hasPagePermission(#projectName, #branchName, #path, EDIT_PAGE)") Map<String, Object> savePageRange(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, @RequestParam String markdown, @RequestParam String range,
			@RequestParam String commit, Authentication authentication, Locale locale, HttpServletRequest request); @RequestMapping(value="/restoreVersion/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}/json", method=RequestMethod.POST) @ResponseBody @PreAuthorize("hasPagePermission(#projectName, #branchName, #path, EDIT_PAGE)") Map<String, Object> restoreVersion(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, @RequestParam String version, Authentication authentication); @RequestMapping(value="/cherryPick/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}", method=RequestMethod.POST) @PreAuthorize("hasPagePermission(#projectName, #branchName, #path, VIEW)") String cherryPick(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, @RequestParam String version1, @RequestParam String version2,
			@RequestParam("branch") Set<String> targetBranches, @RequestParam boolean dryRun,
			WebRequest request, Model model, Authentication authentication, Locale locale); @RequestMapping(value="/split/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}/" + "{rangeStart:[0-9]+},{rangeEnd:[0-9]+}", method=RequestMethod.GET) @PreAuthorize("hasBranchPermission(#projectName, #branchName, EDIT_PAGE)") String splitPage(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, @PathVariable int rangeStart, @PathVariable int rangeEnd,
			Model model); @RequestMapping(value="/saveChildrenOrder/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}/json", method=RequestMethod.POST) @PreAuthorize("hasBranchPermission(#projectName, #branchName, EDIT_PAGE)") @ResponseBody Map<String, Object> saveChildrenOrder(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, @RequestParam(value="childrenOrder[]", required=false) List<String> childrenOrder,
			Authentication authentication); @RequestMapping(value="/resetChildrenOrder/{projectName:" + DocumentrConstants.PROJECT_NAME_PATTERN + "}/" + "{branchName:" + DocumentrConstants.BRANCH_NAME_PATTERN + "}/" + "{path:" + DocumentrConstants.PAGE_PATH_URL_PATTERN + "}/json", method=RequestMethod.GET) @PreAuthorize("hasBranchPermission(#projectName, #branchName, EDIT_PAGE)") @ResponseBody Map<String, Object> resetChildrenOrder(@PathVariable String projectName, @PathVariable String branchName,
			@PathVariable String path, Authentication authentication);  }
@Test public void cherryPick() throws IOException { when(permissionEvaluator.hasPagePermission( authenticatedAuthentication, PROJECT, "targetBranch", PAGE_PATH, Permission.EDIT_PAGE)) .thenReturn(true); when(cherryPicker.getCommitsList(PROJECT, BRANCH, PAGE_PATH, "version2", "version4")) .thenReturn(Lists.newArrayList("version3", "version4")); @SuppressWarnings("nls") List<CommitCherryPickResult> branchResults = Lists.newArrayList( new CommitCherryPickResult(new PageVersion("version3", "user", new Date()), CommitCherryPickResult.Status.OK), new CommitCherryPickResult(new PageVersion("version3", "user", new Date()), CommitCherryPickResult.Status.OK)); SortedMap<String, List<CommitCherryPickResult>> results = Maps.newTreeMap(); results.put("targetBranch", branchResults); when(cherryPicker.cherryPick(PROJECT, BRANCH, PAGE_PATH, Lists.newArrayList("version3", "version4"), Sets.newHashSet("targetBranch"), Collections.<CommitCherryPickConflictResolve>emptySet(), false, USER, LOCALE)) .thenReturn(results); String view = pageController.cherryPick(PROJECT, BRANCH, PAGE_PATH, "version2", "version4", Sets.newHashSet("targetBranch"), false, webRequest, model, authenticatedAuthentication, LOCALE); assertEquals("/page/" + PROJECT + "/" + BRANCH + "/" + PAGE_PATH_URL, removeViewPrefix(view)); assertRedirect(view); }
@Test public void cherryPickWithConflicts() throws IOException { when(permissionEvaluator.hasPagePermission( authenticatedAuthentication, PROJECT, "targetBranch", PAGE_PATH, Permission.EDIT_PAGE)) .thenReturn(true); when(cherryPicker.getCommitsList(PROJECT, BRANCH, PAGE_PATH, "version2", "version4")) .thenReturn(Lists.newArrayList("version3", "version4")); @SuppressWarnings("nls") List<CommitCherryPickResult> branchResults = Lists.newArrayList( new CommitCherryPickResult(new PageVersion("version3", "user", new Date()), CommitCherryPickResult.Status.OK), new CommitCherryPickResult(new PageVersion("version3", "user", new Date()), "conflictText")); SortedMap<String, List<CommitCherryPickResult>> results = Maps.newTreeMap(); results.put("targetBranch", branchResults); when(cherryPicker.cherryPick(PROJECT, BRANCH, PAGE_PATH, Lists.newArrayList("version3", "version4"), Sets.newHashSet("targetBranch"), Collections.<CommitCherryPickConflictResolve>emptySet(), false, USER, LOCALE)) .thenReturn(results); String view = pageController.cherryPick(PROJECT, BRANCH, PAGE_PATH, "version2", "version4", Sets.newHashSet("targetBranch"), false, webRequest, model, authenticatedAuthentication, LOCALE); assertEquals("/project/branch/page/cherryPick", view); verify(model).addAttribute("cherryPickResults", results); verify(model).addAttribute("version1", "version2"); verify(model).addAttribute("version2", "version4"); verify(model).addAttribute("resolves", Collections.emptySet()); }
@Test public void cherryPickWithConflictsAndResolveTexts() throws IOException { when(permissionEvaluator.hasPagePermission( authenticatedAuthentication, PROJECT, "targetBranch", PAGE_PATH, Permission.EDIT_PAGE)) .thenReturn(true); when(cherryPicker.getCommitsList(PROJECT, BRANCH, PAGE_PATH, "version2", "version4")) .thenReturn(Lists.newArrayList("version3", "version4")); @SuppressWarnings("nls") Set<CommitCherryPickConflictResolve> resolves = Sets.newHashSet( new CommitCherryPickConflictResolve("targetBranch", "version3", "resolveText")); @SuppressWarnings("nls") List<CommitCherryPickResult> branchResults = Lists.newArrayList( new CommitCherryPickResult(new PageVersion("version3", "user", new Date()), CommitCherryPickResult.Status.OK), new CommitCherryPickResult(new PageVersion("version3", "user", new Date()), CommitCherryPickResult.Status.OK)); SortedMap<String, List<CommitCherryPickResult>> results = Maps.newTreeMap(); results.put("targetBranch", branchResults); when(cherryPicker.cherryPick(PROJECT, BRANCH, PAGE_PATH, Lists.newArrayList("version3", "version4"), Sets.newHashSet("targetBranch"), resolves, false, USER, LOCALE)) .thenReturn(results); Map<String, String[]> params = Maps.newHashMap(); params.put("resolveText_targetBranch/version3", new String[] { "resolveText" }); when(webRequest.getParameterMap()).thenReturn(params); String view = pageController.cherryPick(PROJECT, BRANCH, PAGE_PATH, "version2", "version4", Sets.newHashSet("targetBranch"), false, webRequest, model, authenticatedAuthentication, LOCALE); assertEquals("/page/" + PROJECT + "/" + BRANCH + "/" + PAGE_PATH_URL, removeViewPrefix(view)); assertRedirect(view); }