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.

branches.ts 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2018 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. import { sortBy } from 'lodash';
  21. export function isBranch(branchLike?: T.BranchLike): branchLike is T.Branch {
  22. return branchLike !== undefined && (branchLike as T.Branch).isMain !== undefined;
  23. }
  24. export function isShortLivingBranch(branchLike?: T.BranchLike): branchLike is T.ShortLivingBranch {
  25. return (
  26. isBranch(branchLike) &&
  27. !branchLike.isMain &&
  28. (branchLike as T.ShortLivingBranch).type === 'SHORT'
  29. );
  30. }
  31. export function isLongLivingBranch(branchLike?: T.BranchLike): branchLike is T.LongLivingBranch {
  32. return (
  33. isBranch(branchLike) && !branchLike.isMain && (branchLike as T.LongLivingBranch).type === 'LONG'
  34. );
  35. }
  36. export function isMainBranch(branchLike?: T.BranchLike): branchLike is T.MainBranch {
  37. return isBranch(branchLike) && branchLike.isMain;
  38. }
  39. export function isPullRequest(branchLike?: T.BranchLike): branchLike is T.PullRequest {
  40. return branchLike !== undefined && (branchLike as T.PullRequest).key !== undefined;
  41. }
  42. export function getPullRequestDisplayName(pullRequest: T.PullRequest) {
  43. return `${pullRequest.key} – ${pullRequest.title}`;
  44. }
  45. export function getBranchLikeDisplayName(branchLike: T.BranchLike) {
  46. return isPullRequest(branchLike) ? getPullRequestDisplayName(branchLike) : branchLike.name;
  47. }
  48. export function getBranchLikeKey(branchLike: T.BranchLike) {
  49. return isPullRequest(branchLike) ? `pull-request-${branchLike.key}` : `branch-${branchLike.name}`;
  50. }
  51. export function getBranchQualityGateColor(status: string) {
  52. let indicatorColor = 'gray';
  53. if (status === 'ERROR') {
  54. indicatorColor = 'red';
  55. } else if (status === 'WARN') {
  56. indicatorColor = 'orange';
  57. } else if (status === 'OK') {
  58. indicatorColor = 'green';
  59. }
  60. return indicatorColor;
  61. }
  62. export function isSameBranchLike(a: T.BranchLike | undefined, b: T.BranchLike | undefined) {
  63. // main branches are always equal
  64. if (isMainBranch(a) && isMainBranch(b)) {
  65. return true;
  66. }
  67. // short- and long-living branches are compared by type and name
  68. if (
  69. (isLongLivingBranch(a) && isLongLivingBranch(b)) ||
  70. (isShortLivingBranch(a) && isShortLivingBranch(b))
  71. ) {
  72. return a.type === b.type && a.name === b.name;
  73. }
  74. // pull requests are compared by id
  75. if (isPullRequest(a) && isPullRequest(b)) {
  76. return a.key === b.key;
  77. }
  78. // finally if both parameters are `undefined`, consider them equal
  79. return a === b;
  80. }
  81. export function sortBranchesAsTree(branchLikes: T.BranchLike[]) {
  82. const result: T.BranchLike[] = [];
  83. const mainBranch = branchLikes.find(isMainBranch);
  84. const longLivingBranches = branchLikes.filter(isLongLivingBranch);
  85. const shortLivingBranches = branchLikes.filter(isShortLivingBranch);
  86. const pullRequests = branchLikes.filter(isPullRequest);
  87. // main branch is always first
  88. if (mainBranch) {
  89. result.push(
  90. mainBranch,
  91. ...getPullRequests(mainBranch.name),
  92. ...getNestedShortLivingBranches(mainBranch.name)
  93. );
  94. }
  95. // then all long-living branches
  96. sortBy(longLivingBranches, 'name').forEach(longLivingBranch => {
  97. result.push(
  98. longLivingBranch,
  99. ...getPullRequests(longLivingBranch.name),
  100. ...getNestedShortLivingBranches(longLivingBranch.name)
  101. );
  102. });
  103. // finally all orhpan pull requests and branches
  104. result.push(
  105. ...sortBy(pullRequests.filter(pr => pr.isOrphan), pullRequest => pullRequest.key),
  106. ...sortBy(shortLivingBranches.filter(branch => branch.isOrphan), branch => branch.name)
  107. );
  108. return result;
  109. /** Get all short-living branches (possibly nested) which should be merged to a given branch */
  110. function getNestedShortLivingBranches(mergeBranch: string) {
  111. const found: T.ShortLivingBranch[] = shortLivingBranches.filter(
  112. branch => branch.mergeBranch === mergeBranch
  113. );
  114. let i = 0;
  115. while (i < found.length) {
  116. const current = found[i];
  117. found.push(...shortLivingBranches.filter(branch => branch.mergeBranch === current.name));
  118. i++;
  119. }
  120. return sortBy(found, branch => branch.name);
  121. }
  122. function getPullRequests(base: string) {
  123. return sortBy(pullRequests.filter(pr => pr.base === base), pullRequest => pullRequest.key);
  124. }
  125. }
  126. export function getBranchLikeQuery(branchLike?: T.BranchLike): T.BranchParameters {
  127. if (isShortLivingBranch(branchLike) || isLongLivingBranch(branchLike)) {
  128. return { branch: branchLike.name };
  129. } else if (isPullRequest(branchLike)) {
  130. return { pullRequest: branchLike.key };
  131. } else {
  132. return {};
  133. }
  134. }
  135. // Create branch object from branch name or pull request key
  136. export function fillBranchLike(
  137. branch?: string,
  138. pullRequest?: string
  139. ): T.ShortLivingBranch | T.PullRequest | undefined {
  140. if (branch) {
  141. return {
  142. isMain: false,
  143. mergeBranch: '',
  144. name: branch,
  145. type: 'SHORT'
  146. } as T.ShortLivingBranch;
  147. } else if (pullRequest) {
  148. return { base: '', branch: '', key: pullRequest, title: '' } as T.PullRequest;
  149. }
  150. return undefined;
  151. }