@@ -45,25 +45,15 @@ const realHasGitFn = () => {
4545const hasGit =
4646 process . env . NODE_ENV === 'test' ? realHasGitFn : _ . memoize ( realHasGitFn ) ;
4747
48- // TODO Docusaurus v4: remove this
49- // Exceptions are not made for control flow logic
50- /** Custom error thrown when git is not found in `PATH`. */
51- class GitNotFoundError extends Error { }
52-
53- // TODO Docusaurus v4: remove this, only kept for retro-compatibility
54- // Exceptions are not made for control flow logic
55- /** Custom error thrown when the current file is not tracked by git. */
56- export class FileNotTrackedError extends Error { }
57-
5848/**
5949 * Fetches the git history of a file and returns a relevant commit date.
6050 * It gets the commit date instead of author date so that amended commits
6151 * can have their dates updated.
6252 *
63- * @throws { @link GitNotFoundError } If git is not found in `PATH` .
64- * @throws { @link FileNotTrackedError } If the current file is not tracked by git.
65- * @throws Also throws when `git log` exited with non-zero, or when it outputs
66- * unexpected text.
53+ * Returns `null` if the file is not tracked by git .
54+ *
55+ * @throws If git is not found in `PATH`, if the file does not exist, if
56+ * `git log` exited with non-zero, or if it outputs unexpected text.
6757 */
6858export async function getFileCommitDate (
6959 /** Absolute path to the file. */
@@ -82,16 +72,16 @@ export async function getFileCommitDate(
8272 date : Date ; // TODO duplicate data, not really useful?
8373 /** Timestamp returned from git, converted to **milliseconds**. */
8474 timestamp : number ;
85- } > ;
75+ } | null > ;
8676/**
8777 * Fetches the git history of a file and returns a relevant commit date.
8878 * It gets the commit date instead of author date so that amended commits
8979 * can have their dates updated.
9080 *
91- * @throws { @link GitNotFoundError } If git is not found in `PATH` .
92- * @throws { @link FileNotTrackedError } If the current file is not tracked by git.
93- * @throws Also throws when `git log` exited with non-zero, or when it outputs
94- * unexpected text.
81+ * Returns `null` if the file is not tracked by git .
82+ *
83+ * @throws If git is not found in `PATH`, if the file does not exist, if
84+ * `git log` exited with non-zero, or if it outputs unexpected text.
9585 */
9686export async function getFileCommitDate (
9787 /** Absolute path to the file. */
@@ -111,7 +101,7 @@ export async function getFileCommitDate(
111101 timestamp : number ;
112102 /** The author's name, as returned from git. */
113103 author : string ;
114- } > ;
104+ } | null > ;
115105
116106export async function getFileCommitDate (
117107 file : string ,
@@ -126,9 +116,9 @@ export async function getFileCommitDate(
126116 date : Date ;
127117 timestamp : number ;
128118 author ?: string ;
129- } > {
119+ } | null > {
130120 if ( ! hasGit ( ) ) {
131- throw new GitNotFoundError (
121+ throw new Error (
132122 `Failed to retrieve git history for "${ file } " because git is not installed.` ,
133123 ) ;
134124 }
@@ -172,10 +162,9 @@ export async function getFileCommitDate(
172162
173163 const output = result . stdout . trim ( ) ;
174164
165+ // No output: the file is not tracked by git
175166 if ( ! output ) {
176- throw new FileNotTrackedError (
177- `Failed to retrieve the git history for file "${ file } " because the file is not tracked by git.` ,
178- ) ;
167+ return null ;
179168 }
180169
181170 const match = output . match ( regex ) ;
@@ -196,8 +185,8 @@ export async function getFileCommitDate(
196185 return { date, timestamp} ;
197186}
198187
199- let showedGitRequirementError = false ;
200- let showedFileNotTrackedError = false ;
188+ let showedGitRequirementWarning = false ;
189+ let showedFileNotTrackedWarning = false ;
201190
202191type GitCommitInfo = { timestamp : number ; author : string } ;
203192
@@ -208,38 +197,34 @@ async function getGitCommitInfo(
208197 if ( ! filePath ) {
209198 return null ;
210199 }
211- // Wrap in try/catch in case the shell commands fail
212- // (e.g. project doesn't use Git, etc).
213- try {
214- const result = await getFileCommitDate ( filePath , {
215- age,
216- includeAuthor : true ,
217- } ) ;
218- return { timestamp : result . timestamp , author : result . author } ;
219- } catch ( err ) {
220- // TODO legacy perf issue: do not use exceptions for control flow!
221- if ( err instanceof GitNotFoundError ) {
222- if ( ! showedGitRequirementError ) {
223- logger . warn ( 'Sorry, the last update options require Git.' ) ;
224- showedGitRequirementError = true ;
225- }
226- } else if ( err instanceof FileNotTrackedError ) {
227- if ( ! showedFileNotTrackedError ) {
228- logger . warn (
229- 'Cannot infer the update date for some files, as they are not tracked by git.' ,
230- ) ;
231- showedFileNotTrackedError = true ;
232- }
233- } else {
234- throw new Error (
235- `An error occurred when trying to get the file ${
236- age === 'oldest' ? 'creation' : 'last update'
237- } date from Git`,
238- { cause : err } ,
200+ if ( ! hasGit ( ) ) {
201+ if ( ! showedGitRequirementWarning ) {
202+ logger . warn ( 'Sorry, the last update options require Git.' ) ;
203+ showedGitRequirementWarning = true ;
204+ }
205+ return null ;
206+ }
207+ const result = await getFileCommitDate ( filePath , {
208+ age,
209+ includeAuthor : true ,
210+ } ) . catch ( ( err ) => {
211+ throw new Error (
212+ `An error occurred when trying to get the file ${
213+ age === 'oldest' ? 'creation' : 'last update'
214+ } date from Git`,
215+ { cause : err } ,
216+ ) ;
217+ } ) ;
218+ if ( ! result ) {
219+ if ( ! showedFileNotTrackedWarning ) {
220+ logger . warn (
221+ 'Cannot infer the update date for some files, as they are not tracked by git.' ,
239222 ) ;
223+ showedFileNotTrackedWarning = true ;
240224 }
241225 return null ;
242226 }
227+ return { timestamp : result . timestamp , author : result . author } ;
243228}
244229
245230export async function getGitLastUpdate (
0 commit comments