33/**
44 * Checkout Gutenberg Repository Script
55 *
6- * This script checks out the Gutenberg repository at a specific commit/branch/tag
7- * as specified in the root package.json's "gutenberg" configuration.
8- *
9- * It handles:
10- * - Initial clone if directory doesn't exist
11- * - Updating existing checkout to correct ref
12- * - Installing dependencies with npm ci
13- * - Idempotent operation (safe to run multiple times)
6+ * Clones the Gutenberg repository at the SHA pinned in package.json into the
7+ * gutenberg/ directory, then installs its dependencies. Only runs in local
8+ * repository mode (GUTENBERG_LOCAL_REPO=true). Pass --force to remove an
9+ * existing clone and start fresh.
1410 *
1511 * @package WordPress
1612 */
1713
1814const { spawn } = require ( 'child_process' ) ;
1915const fs = require ( 'fs' ) ;
2016const path = require ( 'path' ) ;
21- const { readGutenbergConfig, isLocalRepoMode, isGutenbergRepoClone , writeRepoHash } = require ( './utils' ) ;
17+ const { readGutenbergConfig, isLocalRepoMode, writeRepoHash } = require ( './utils' ) ;
2218
2319// Constants
2420const GUTENBERG_REPO = 'https://github.com/WordPress/gutenberg.git' ;
@@ -98,15 +94,14 @@ async function main( force ) {
9894 return ;
9995 }
10096
101- if ( ! force && isGutenbergRepoClone ( ) ) {
102- console . log ( 'ℹ️ The `gutenberg` directory is already a git clone .' ) ;
97+ if ( ! force && fs . existsSync ( gutenbergDir ) ) {
98+ console . log ( 'ℹ️ The `gutenberg` directory already exists .' ) ;
10399 console . log ( ' Use `npm run grunt gutenberg:checkout -- --force` to remove and re-clone.' ) ;
104100 return ;
105101 }
106102
107103 console . log ( '🔍 Checking Gutenberg configuration...' ) ;
108104
109- // Read Gutenberg SHA from package.json
110105 let ref ;
111106 try {
112107 ( { sha : ref } = readGutenbergConfig ( ) ) ;
@@ -117,79 +112,41 @@ async function main( force ) {
117112 process . exit ( 1 ) ;
118113 }
119114
120- // Check if Gutenberg directory exists
121- const gutenbergExists = fs . existsSync ( gutenbergDir ) ;
122-
123- if ( ! gutenbergExists ) {
124- console . log ( '\n📥 Cloning Gutenberg repository (shallow clone)...' ) ;
125- try {
126- /*
127- * Generic shallow clone approach that works for both branches and commit hashes.
128- * 1. Clone with no checkout and shallow depth.
129- */
130- await exec ( 'git' , [
131- 'clone' ,
132- '--depth' ,
133- '1' ,
134- '--no-checkout' ,
135- GUTENBERG_REPO ,
136- 'gutenberg' ,
137- ] ) ;
138-
139- // 2. Fetch the specific ref with depth 1 (works for branches, tags, and commits)
140- await exec ( 'git' , [ 'fetch' , '--depth' , '1' , 'origin' , ref ] , {
141- cwd : gutenbergDir ,
142- } ) ;
143-
144- // 3. Checkout FETCH_HEAD
145- await exec ( 'git' , [ 'checkout' , 'FETCH_HEAD' ] , {
146- cwd : gutenbergDir ,
147- } ) ;
148-
149- console . log ( '✅ Cloned successfully' ) ;
150- } catch ( error ) {
151- console . error ( '❌ Clone failed:' , error . message ) ;
152- process . exit ( 1 ) ;
153- }
154- } else {
155- console . log ( '\n✅ Gutenberg directory already exists' ) ;
115+ if ( force && fs . existsSync ( gutenbergDir ) ) {
116+ console . log ( '\n🗑️ Removing existing gutenberg directory...' ) ;
117+ fs . rmSync ( gutenbergDir , { recursive : true , force : true } ) ;
156118 }
157119
158- // Fetch and checkout target ref
159- console . log ( `\n📡 Fetching and checking out: ${ ref } ` ) ;
120+ console . log ( '\n📥 Cloning Gutenberg repository (shallow clone)...' ) ;
160121 try {
161- // Fetch the specific ref (works for branches, tags, and commit hashes).
122+ /*
123+ * Two-step shallow clone that works for both branches and commit SHAs.
124+ * `git clone` alone cannot shallow-clone an arbitrary commit hash, so
125+ * we clone with --no-checkout then fetch the pinned ref explicitly.
126+ */
127+ await exec ( 'git' , [
128+ 'clone' ,
129+ '--depth' , '1' ,
130+ '--no-checkout' ,
131+ GUTENBERG_REPO ,
132+ 'gutenberg' ,
133+ ] ) ;
134+
162135 await exec ( 'git' , [ 'fetch' , '--depth' , '1' , 'origin' , ref ] , {
163136 cwd : gutenbergDir ,
164137 } ) ;
165138
166- if ( force ) {
167- // Hard-reset the index and working tree to FETCH_HEAD, discarding any local modifications.
168- await exec ( 'git' , [ 'reset' , '--hard' , 'FETCH_HEAD' ] , {
169- cwd : gutenbergDir ,
170- } ) ;
171- } else {
172- await exec ( 'git' , [ 'checkout' , 'FETCH_HEAD' ] , {
173- cwd : gutenbergDir ,
174- } ) ;
175- }
139+ await exec ( 'git' , [ 'checkout' , 'FETCH_HEAD' ] , {
140+ cwd : gutenbergDir ,
141+ } ) ;
176142
177- console . log ( '✅ Checked out successfully' ) ;
143+ console . log ( '✅ Cloned successfully' ) ;
178144 } catch ( error ) {
179- console . error ( '❌ Fetch/checkout failed:' , error . message ) ;
145+ console . error ( '❌ Clone failed:' , error . message ) ;
180146 process . exit ( 1 ) ;
181147 }
182148
183- // Install dependencies
184- console . log ( '\n📦 Installing dependencies...' ) ;
185- const nodeModulesExists = fs . existsSync (
186- path . join ( gutenbergDir , 'node_modules' )
187- ) ;
188-
189- if ( ! nodeModulesExists ) {
190- console . log ( ' (This may take a few minutes on first run)' ) ;
191- }
192-
149+ console . log ( '\n📦 Installing dependencies (this may take a few minutes)...' ) ;
193150 try {
194151 await exec ( 'npm' , [ 'ci' ] , { cwd : gutenbergDir } ) ;
195152 console . log ( '✅ Dependencies installed' ) ;
0 commit comments