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.

MergeMessageFormatter.java 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * Copyright (C) 2010-2012, Robin Stocker <robin@nibor.org> and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.merge;
  11. import java.util.ArrayList;
  12. import java.util.List;
  13. import org.eclipse.jgit.lib.Constants;
  14. import org.eclipse.jgit.lib.ObjectId;
  15. import org.eclipse.jgit.lib.Ref;
  16. import org.eclipse.jgit.lib.Repository;
  17. import org.eclipse.jgit.util.ChangeIdUtil;
  18. import org.eclipse.jgit.util.StringUtils;
  19. /**
  20. * Formatter for constructing the commit message for a merge commit.
  21. * <p>
  22. * The format should be the same as C Git does it, for compatibility.
  23. */
  24. public class MergeMessageFormatter {
  25. /**
  26. * Construct the merge commit message.
  27. *
  28. * @param refsToMerge
  29. * the refs which will be merged
  30. * @param target
  31. * the branch ref which will be merged into
  32. * @return merge commit message
  33. */
  34. public String format(List<Ref> refsToMerge, Ref target) {
  35. StringBuilder sb = new StringBuilder();
  36. sb.append("Merge "); //$NON-NLS-1$
  37. List<String> branches = new ArrayList<>();
  38. List<String> remoteBranches = new ArrayList<>();
  39. List<String> tags = new ArrayList<>();
  40. List<String> commits = new ArrayList<>();
  41. List<String> others = new ArrayList<>();
  42. for (Ref ref : refsToMerge) {
  43. if (ref.getName().startsWith(Constants.R_HEADS)) {
  44. branches.add("'" + Repository.shortenRefName(ref.getName()) //$NON-NLS-1$
  45. + "'"); //$NON-NLS-1$
  46. } else if (ref.getName().startsWith(Constants.R_REMOTES)) {
  47. remoteBranches.add("'" //$NON-NLS-1$
  48. + Repository.shortenRefName(ref.getName()) + "'"); //$NON-NLS-1$
  49. } else if (ref.getName().startsWith(Constants.R_TAGS)) {
  50. tags.add("'" + Repository.shortenRefName(ref.getName()) + "'"); //$NON-NLS-1$ //$NON-NLS-2$
  51. } else {
  52. ObjectId objectId = ref.getObjectId();
  53. if (objectId != null && ref.getName().equals(objectId.getName())) {
  54. commits.add("'" + ref.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
  55. } else {
  56. others.add(ref.getName());
  57. }
  58. }
  59. }
  60. List<String> listings = new ArrayList<>();
  61. if (!branches.isEmpty())
  62. listings.add(joinNames(branches, "branch", "branches")); //$NON-NLS-1$//$NON-NLS-2$
  63. if (!remoteBranches.isEmpty())
  64. listings.add(joinNames(remoteBranches, "remote-tracking branch", //$NON-NLS-1$
  65. "remote-tracking branches")); //$NON-NLS-1$
  66. if (!tags.isEmpty())
  67. listings.add(joinNames(tags, "tag", "tags")); //$NON-NLS-1$ //$NON-NLS-2$
  68. if (!commits.isEmpty())
  69. listings.add(joinNames(commits, "commit", "commits")); //$NON-NLS-1$ //$NON-NLS-2$
  70. if (!others.isEmpty())
  71. listings.add(StringUtils.join(others, ", ", " and ")); //$NON-NLS-1$ //$NON-NLS-2$
  72. sb.append(StringUtils.join(listings, ", ")); //$NON-NLS-1$
  73. String targetName = target.getLeaf().getName();
  74. if (!targetName.equals(Constants.R_HEADS + Constants.MASTER)) {
  75. String targetShortName = Repository.shortenRefName(targetName);
  76. sb.append(" into " + targetShortName); //$NON-NLS-1$
  77. }
  78. return sb.toString();
  79. }
  80. /**
  81. * Add section with conflicting paths to merge message.
  82. *
  83. * @param message
  84. * the original merge message
  85. * @param conflictingPaths
  86. * the paths with conflicts
  87. * @return merge message with conflicting paths added
  88. */
  89. public String formatWithConflicts(String message,
  90. List<String> conflictingPaths) {
  91. StringBuilder sb = new StringBuilder();
  92. String[] lines = message.split("\n"); //$NON-NLS-1$
  93. int firstFooterLine = ChangeIdUtil.indexOfFirstFooterLine(lines);
  94. for (int i = 0; i < firstFooterLine; i++)
  95. sb.append(lines[i]).append('\n');
  96. if (firstFooterLine == lines.length && message.length() != 0)
  97. sb.append('\n');
  98. addConflictsMessage(conflictingPaths, sb);
  99. if (firstFooterLine < lines.length)
  100. sb.append('\n');
  101. for (int i = firstFooterLine; i < lines.length; i++)
  102. sb.append(lines[i]).append('\n');
  103. return sb.toString();
  104. }
  105. private static void addConflictsMessage(List<String> conflictingPaths,
  106. StringBuilder sb) {
  107. sb.append("Conflicts:\n"); //$NON-NLS-1$
  108. for (String conflictingPath : conflictingPaths) {
  109. sb.append('\t').append(conflictingPath).append('\n');
  110. }
  111. }
  112. private static String joinNames(List<String> names, String singular,
  113. String plural) {
  114. if (names.size() == 1) {
  115. return singular + " " + names.get(0); //$NON-NLS-1$
  116. }
  117. return plural + " " + StringUtils.join(names, ", ", " and "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  118. }
  119. }