Showing the changes to packages/shared/src/sourceControl.ts (1 of 172 files). Show all
Unified · Split
| @@ -1,4 +1,8 @@ | |||
| 1 | import type { SourceControlProviderInfo, SourceControlProviderKind } from "@t3tools/contracts"; | 1 | import type { |
| 2 | RepositoryIdentity, | ||
| 3 | SourceControlProviderInfo, | ||
| 4 | SourceControlProviderKind, | ||
| 5 | } from "@t3tools/contracts"; | ||
| 2 | 6 | ||
| 3 | export interface ChangeRequestPresentation { | 7 | export interface ChangeRequestPresentation { |
| 4 | readonly icon: "github" | "gitlab" | "azure-devops" | "bitbucket" | "change-request"; | 8 | readonly icon: "github" | "gitlab" | "azure-devops" | "bitbucket" | "change-request"; |
| @@ -234,3 +238,43 @@ export function detectSourceControlProviderFromRemoteUrl( · 229 unmodified lines | |||
| 234 | baseUrl: toBaseUrl(host), | 238 | baseUrl: toBaseUrl(host), |
| 235 | }; | 239 | }; |
| 236 | } | 240 | } |
| 241 | |||
| 242 | /** | ||
| 243 | * The provider-native repository selector. `displayName` is the full path below the host, which | ||
| 244 | * is what nested GitLab groups need; owner/name is the two-segment fallback for identities | ||
| 245 | * recorded before that field existed. | ||
| 246 | * | ||
| 247 | * Azure DevOps is the exception: `az repos pr list --repository` takes a repository name, and | ||
| 248 | * takes the organisation and project from the checkout it detects — so the recorded | ||
| 249 | * `org/project/_git/repo` path is refused outright and the whole repository reads as | ||
| 250 | * unavailable. Its name is the last segment, which is what this hands over. | ||
| 251 | * | ||
| 252 | * One function because everything downstream is keyed by what it answers: the rows' own | ||
| 253 | * `repository`, the per-repository cursors, and the detail and diff reads a row leads to. | ||
| 254 | */ | ||
| 255 | export function sourceControlRepositorySelector( | ||
| 256 | identity: | ||
| 257 | | Pick<RepositoryIdentity, "provider" | "displayName" | "owner" | "name"> | ||
| 258 | | null | ||
| 259 | | undefined, | ||
| 260 | ): string | null { | ||
| 261 | if (!identity) return null; | ||
| 262 | if (identity.provider === "azure-devops") { | ||
| 263 | const segments = (identity.displayName ?? "").split("/").filter((part) => part !== "_git"); | ||
| 264 | return identity.name || segments.at(-1) || null; | ||
| 265 | } | ||
| 266 | if (identity.displayName) return identity.displayName; | ||
| 267 | return identity.owner && identity.name ? `${identity.owner}/${identity.name}` : null; | ||
| 268 | } | ||
| 269 | |||
| 270 | export function canonicalRepositoryKey(key: string): string { | ||
| 271 | return key | ||
| 272 | .replace( | ||
| 273 | /^(?:ssh\.dev\.azure\.com|vs-ssh\.visualstudio\.com)\/v3\/([^/]+)\/([^/]+)\/([^/]+)$/u, | ||
| 274 | "dev.azure.com/$1/$2/_git/$3", | ||
| 275 | ) | ||
| 276 | .replace( | ||
| 277 | /^([^.]+)\.visualstudio\.com\/(?:defaultcollection\/)?([^/]+)\/_git\/([^/]+)$/u, | ||
| 278 | "dev.azure.com/$1/$2/_git/$3", | ||
| 279 | ); | ||
| 280 | } | ||