| ... | @@ -61,6 +61,8 @@ const LIST_REFS_SNAPSHOT_CACHE_CAPACITY = 64; | ... | @@ -61,6 +61,8 @@ const LIST_REFS_SNAPSHOT_CACHE_CAPACITY = 64; |
| 61 | const LIST_REFS_SNAPSHOT_CACHE_TTL = Duration.minutes(2); | 61 | const LIST_REFS_SNAPSHOT_CACHE_TTL = Duration.minutes(2); |
| 62 | const LIST_REFS_REFRESH_COALESCE_TTL = Duration.seconds(5); | 62 | const LIST_REFS_REFRESH_COALESCE_TTL = Duration.seconds(5); |
| 63 | const LIST_REFS_REFRESH_FAILURE_COOLDOWN = Duration.seconds(30); | 63 | const LIST_REFS_REFRESH_FAILURE_COOLDOWN = Duration.seconds(30); |
| | 64 | const STATUS_DEFAULT_BRANCH_CACHE_TTL = Duration.minutes(5); |
| | 65 | const STATUS_ORIGIN_EXISTS_CACHE_TTL = Duration.minutes(5); |
| 64 | const STATUS_UPSTREAM_REFRESH_ENV = Object.freeze({ | 66 | const STATUS_UPSTREAM_REFRESH_ENV = Object.freeze({ |
| 65 | GCM_INTERACTIVE: "never", | 67 | GCM_INTERACTIVE: "never", |
| 66 | GIT_ASKPASS: "", | 68 | GIT_ASKPASS: "", |
| ... | @@ -1119,6 +1121,63 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* | ... | @@ -1119,6 +1121,63 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* |
| 1119 | return Cache.get(refresh ? repositoryPathsRefreshCache : repositoryPathsCache, cacheKey); | 1121 | return Cache.get(refresh ? repositoryPathsRefreshCache : repositoryPathsCache, cacheKey); |
| 1120 | }; | 1122 | }; |
| 1121 | | 1123 | |
| | 1124 | const defaultBranchCache = yield* Cache.makeWith( |
| | 1125 | (gitCommonDir: string) => |
| | 1126 | Effect.gen(function* () { |
| | 1127 | const path = yield* Path.Path; |
| | 1128 | const fetchCwd = |
| | 1129 | path.basename(gitCommonDir) === ".git" ? path.dirname(gitCommonDir) : gitCommonDir; |
| | 1130 | return yield* executeGit( |
| | 1131 | "GitVcsDriver.statusDetails.defaultBranch", |
| | 1132 | fetchCwd, |
| | 1133 | ["--git-dir", gitCommonDir, "symbolic-ref", "refs/remotes/origin/HEAD"], |
| | 1134 | { allowNonZeroExit: true }, |
| | 1135 | ).pipe( |
| | 1136 | Effect.map((result) => { |
| | 1137 | if (result.exitCode !== 0) return null; |
| | 1138 | return parseDefaultBranchFromRemoteHeadRef(result.stdout, "origin"); |
| | 1139 | }), |
| | 1140 | ); |
| | 1141 | }), |
| | 1142 | { |
| | 1143 | capacity: 2_048, |
| | 1144 | timeToLive: Exit.match({ |
| | 1145 | onSuccess: () => STATUS_DEFAULT_BRANCH_CACHE_TTL, |
| | 1146 | onFailure: () => Duration.zero, |
| | 1147 | }), |
| | 1148 | }, |
| | 1149 | ); |
| | 1150 | const originExistsCache = yield* Cache.makeWith( |
| | 1151 | (gitCommonDir: string) => |
| | 1152 | Effect.gen(function* () { |
| | 1153 | const path = yield* Path.Path; |
| | 1154 | const fetchCwd = |
| | 1155 | path.basename(gitCommonDir) === ".git" ? path.dirname(gitCommonDir) : gitCommonDir; |
| | 1156 | return yield* executeGit( |
| | 1157 | "GitVcsDriver.statusDetails.originExists", |
| | 1158 | fetchCwd, |
| | 1159 | ["--git-dir", gitCommonDir, "remote", "get-url", "origin"], |
| | 1160 | { allowNonZeroExit: true }, |
| | 1161 | ).pipe(Effect.map((result) => result.exitCode === 0)); |
| | 1162 | }), |
| | 1163 | { |
| | 1164 | capacity: 2_048, |
| | 1165 | timeToLive: Exit.match({ |
| | 1166 | onSuccess: () => STATUS_ORIGIN_EXISTS_CACHE_TTL, |
| | 1167 | onFailure: () => Duration.zero, |
| | 1168 | }), |
| | 1169 | }, |
| | 1170 | ); |
| | 1171 | const invalidateStatusStaticCaches = (cwd: string) => |
| | 1172 | Effect.gen(function* () { |
| | 1173 | const repositoryPaths = yield* resolveRepositoryPaths(cwd).pipe( |
| | 1174 | Effect.catchTags({ GitCommandError: () => Effect.succeed(null) }), |
| | 1175 | ); |
| | 1176 | const cacheKey = repositoryPaths?.gitCommonDir ?? normalizeRepositoryPathsCacheKey(cwd); |
| | 1177 | yield* Cache.invalidate(defaultBranchCache, cacheKey); |
| | 1178 | yield* Cache.invalidate(originExistsCache, cacheKey); |
| | 1179 | }); |
| | 1180 | |
| 1122 | const resolveGitCommonDir = Effect.fn("resolveGitCommonDir")(function* (cwd: string) { | 1181 | const resolveGitCommonDir = Effect.fn("resolveGitCommonDir")(function* (cwd: string) { |
| 1123 | const repositoryPaths = yield* resolveRepositoryPaths(cwd); | 1182 | const repositoryPaths = yield* resolveRepositoryPaths(cwd); |
| 1124 | if (repositoryPaths !== null) { | 1183 | if (repositoryPaths !== null) { |
| ... | @@ -1517,7 +1576,11 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* | ... | @@ -1517,7 +1576,11 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* |
| 1517 | }); | 1576 | }); |
| 1518 | } | 1577 | } |
| 1519 | | 1578 | |
| 1520 | const [numstatStdout, defaultRefResult, hasPrimaryRemote] = yield* Effect.all( | 1579 | const repositoryPaths = yield* resolveRepositoryPaths(cwd).pipe( |
| | 1580 | Effect.catchTags({ GitCommandError: () => Effect.succeed(null) }), |
| | 1581 | ); |
| | 1582 | const statusCacheKey = repositoryPaths?.gitCommonDir; |
| | 1583 | const [numstatStdout, defaultBranch, hasPrimaryRemote] = yield* Effect.all( |
| 1521 | [ | 1584 | [ |
| 1522 | executeGitWithStableDiagnostics( | 1585 | executeGitWithStableDiagnostics( |
| 1523 | "GitVcsDriver.statusDetails.numstat", | 1586 | "GitVcsDriver.statusDetails.numstat", |
| ... | @@ -1574,21 +1637,16 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* | ... | @@ -1574,21 +1637,16 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* |
| 1574 | ); | 1637 | ); |
| 1575 | }), | 1638 | }), |
| 1576 | ), | 1639 | ), |
| 1577 | executeGit( | 1640 | statusCacheKey |
| 1578 | "GitVcsDriver.statusDetails.defaultRef", | 1641 | ? Cache.get(defaultBranchCache, statusCacheKey).pipe(Effect.orElseSucceed(() => null)) |
| 1579 | cwd, | 1642 | : resolveDefaultBranchName(cwd, "origin").pipe(Effect.orElseSucceed(() => null)), |
| 1580 | ["symbolic-ref", "refs/remotes/origin/HEAD"], | 1643 | statusCacheKey |
| 1581 | { allowNonZeroExit: true }, | 1644 | ? Cache.get(originExistsCache, statusCacheKey).pipe(Effect.orElseSucceed(() => false)) |
| 1582 | ), | 1645 | : originRemoteExists(cwd).pipe(Effect.orElseSucceed(() => false)), |
| 1583 | originRemoteExists(cwd).pipe(Effect.orElseSucceed(() => false)), | | |
| 1584 | ], | 1646 | ], |
| 1585 | { concurrency: "unbounded" }, | 1647 | { concurrency: "unbounded" }, |
| 1586 | ); | 1648 | ); |
| 1587 | const statusStdout = statusResult.stdout; | 1649 | const statusStdout = statusResult.stdout; |
| 1588 | const defaultBranch = | | |
| 1589 | defaultRefResult.exitCode === 0 | | |
| 1590 | ? defaultRefResult.stdout.trim().replace(/^refs\/remotes\/origin\//, "") | | |
| 1591 | : null; | | |
| 1592 | | 1650 | |
| 1593 | let refName: string | null = null; | 1651 | let refName: string | null = null; |
| 1594 | let upstreamRef: string | null = null; | 1652 | let upstreamRef: string | null = null; |
| ... | @@ -2809,7 +2867,14 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* | ... | @@ -2809,7 +2867,14 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* |
| 2809 | cwd: string, | 2867 | cwd: string, |
| 2810 | effect: Effect.Effect<A, E>, | 2868 | effect: Effect.Effect<A, E>, |
| 2811 | ): Effect.Effect<A, E> => | 2869 | ): Effect.Effect<A, E> => |
| 2812 | effect.pipe(Effect.ensuring(invalidateListRefsSnapshot(cwd).pipe(Effect.ignore))); | 2870 | effect.pipe( |
| | 2871 | Effect.ensuring( |
| | 2872 | Effect.all([ |
| | 2873 | invalidateListRefsSnapshot(cwd).pipe(Effect.ignore), |
| | 2874 | invalidateStatusStaticCaches(cwd).pipe(Effect.ignore), |
| | 2875 | ]), |
| | 2876 | ), |
| | 2877 | ); |
| 2813 | const initRepoWithListRefsInvalidation: GitVcsDriver.GitVcsDriver["Service"]["initRepo"] = ( | 2878 | const initRepoWithListRefsInvalidation: GitVcsDriver.GitVcsDriver["Service"]["initRepo"] = ( |
| 2814 | input, | 2879 | input, |
| 2815 | ) => | 2880 | ) => |