Skip to content

Commit 574bde9

Browse files
authored
[eas-cli] Do not include files deleted in working directory (#2900)
<!-- If this PR requires a changelog entry, add it by commenting the PR with the command `/changelog-entry [breaking-change|new-feature|bug-fix|chore] [message]`. --> <!-- You can skip the changelog check by labeling the PR with "no changelog". --> # Why When we `git clone` the source repository and then copy worktree changes over, we add and modify files. However, we do not _delete_ files that have been deleted in worktree. # How When we operate in `requireCommit: false` mode, we add `--no-checkout` to the `git clone` command. This way the destination directory only has `.git` directory when we start copying files over. Thus, files deleted from worktree will not suddenly appear in tarball. In `requireCommit: true` mode we don't add `--no-checkout`, because we don't copy files. # Test Plan Added test. Tested manually. Side effect of this is that `git status` reports that all files have been deleted and there's a bunch of untracked files (which, `git add`-ed, make the repository appear as the source repo). I don't know how to copy the Git index 1-1…
1 parent 78837a4 commit 574bde9

File tree

4 files changed

+79
-18
lines changed

4 files changed

+79
-18
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252

5353
notify-slack:
5454
runs-on: ubuntu-latest
55-
needs: test
55+
needs: [test]
5656
name: Notify Slack
5757
if: ${{ github.ref == 'refs/heads/main' && always() }}
5858
steps:

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ This is the log of notable changes to EAS CLI and related packages.
1010

1111
### 🐛 Bug fixes
1212

13+
- Fix files deleted in working directory not being removed from the project archive when `requireCommit` is false. ([#2900](https://github.com/expo/eas-cli/pull/2900) by [@sjchmiela](https://github.com/sjchmiela))
14+
1315
### 🧹 Chores
1416

1517
## [15.0.9](https://github.com/expo/eas-cli/releases/tag/v15.0.9) - 2025-02-09

packages/eas-cli/src/vcs/clients/__tests__/git.test.ts

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -131,31 +131,78 @@ describe('git', () => {
131131
);
132132
});
133133
});
134+
135+
it('is able to delete a submodule ignored by .easignore', async () => {
136+
const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'eas-cli-git-test-'));
137+
await spawnAsync('git', ['init'], { cwd: repoRoot });
138+
const vcs = new GitClient({
139+
requireCommit: false,
140+
maybeCwdOverride: repoRoot,
141+
});
142+
143+
await spawnAsync(
144+
'git',
145+
['submodule', 'add', 'https://github.com/expo/results.git', 'results'],
146+
{ cwd: repoRoot }
147+
);
148+
await spawnAsync('git', ['add', 'results'], { cwd: repoRoot });
149+
await spawnAsync('git', ['commit', '-m', 'add submodule'], { cwd: repoRoot });
150+
151+
const repoCloneNonIgnored = await fs.mkdtemp(path.join(os.tmpdir(), 'eas-cli-git-test-'));
152+
await expect(vcs.makeShallowCopyAsync(repoCloneNonIgnored)).resolves.not.toThrow();
153+
await expect(fs.stat(path.join(repoCloneNonIgnored, 'results'))).resolves.not.toThrow();
154+
155+
await fs.writeFile(`${repoRoot}/.easignore`, 'results');
156+
const repoCloneIgnored = await fs.mkdtemp(path.join(os.tmpdir(), 'eas-cli-git-test-'));
157+
await expect(vcs.makeShallowCopyAsync(repoCloneIgnored)).resolves.not.toThrow();
158+
await expect(fs.stat(path.join(repoCloneIgnored, 'results'))).rejects.toThrow('ENOENT');
159+
});
134160
});
135161

136-
it('is able to delete a submodule ignored by .easignore', async () => {
162+
it('does not include files that have been removed in the working directory', async () => {
137163
const repoRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'eas-cli-git-test-'));
138164
await spawnAsync('git', ['init'], { cwd: repoRoot });
139165
const vcs = new GitClient({
140166
requireCommit: false,
141167
maybeCwdOverride: repoRoot,
142168
});
143169

144-
await spawnAsync(
145-
'git',
146-
['submodule', 'add', 'https://github.com/expo/results.git', 'results'],
147-
{ cwd: repoRoot }
170+
await fs.writeFile(`${repoRoot}/committed-file.txt`, 'file');
171+
await fs.writeFile(`${repoRoot}/file-to-remove.txt`, 'file');
172+
await spawnAsync('git', ['add', 'committed-file.txt', 'file-to-remove.txt'], {
173+
cwd: repoRoot,
174+
});
175+
await spawnAsync('git', ['commit', '-m', 'add files'], { cwd: repoRoot });
176+
177+
await fs.rm(`${repoRoot}/file-to-remove.txt`);
178+
await spawnAsync('git', ['add', 'file-to-remove.txt'], { cwd: repoRoot });
179+
await spawnAsync('git', ['commit', '-m', 'remove file'], { cwd: repoRoot });
180+
181+
await fs.writeFile(`${repoRoot}/new-file.txt`, 'file');
182+
await fs.writeFile(`${repoRoot}/new-tracked-file.txt`, 'file');
183+
184+
const repoClone = await fs.mkdtemp(path.join(os.tmpdir(), 'eas-cli-git-test-'));
185+
await expect(vcs.makeShallowCopyAsync(repoClone)).resolves.not.toThrow();
186+
await expect(fs.stat(path.join(repoClone, 'file-to-remove.txt'))).rejects.toThrow('ENOENT');
187+
await expect(fs.stat(path.join(repoClone, 'committed-file.txt'))).resolves.not.toThrow();
188+
await expect(fs.stat(path.join(repoClone, 'new-file.txt'))).resolves.not.toThrow();
189+
await expect(fs.stat(path.join(repoClone, 'new-tracked-file.txt'))).resolves.not.toThrow();
190+
191+
vcs.requireCommit = true;
192+
await spawnAsync('git', ['add', '.'], { cwd: repoRoot });
193+
await spawnAsync('git', ['commit', '-m', 'tmp commit'], { cwd: repoRoot });
194+
195+
const requireCommitClone = await fs.mkdtemp(path.join(os.tmpdir(), 'eas-cli-git-test-'));
196+
await expect(vcs.makeShallowCopyAsync(requireCommitClone)).resolves.not.toThrow();
197+
await expect(fs.stat(path.join(requireCommitClone, 'file-to-remove.txt'))).rejects.toThrow(
198+
'ENOENT'
148199
);
149-
await spawnAsync('git', ['add', 'results'], { cwd: repoRoot });
150-
await spawnAsync('git', ['commit', '-m', 'add submodule'], { cwd: repoRoot });
151-
152-
const repoCloneNonIgnored = await fs.mkdtemp(path.join(os.tmpdir(), 'eas-cli-git-test-'));
153-
await expect(vcs.makeShallowCopyAsync(repoCloneNonIgnored)).resolves.not.toThrow();
154-
await expect(fs.stat(path.join(repoCloneNonIgnored, 'results'))).resolves.not.toThrow();
155-
156-
await fs.writeFile(`${repoRoot}/.easignore`, 'results');
157-
const repoCloneIgnored = await fs.mkdtemp(path.join(os.tmpdir(), 'eas-cli-git-test-'));
158-
await expect(vcs.makeShallowCopyAsync(repoCloneIgnored)).resolves.not.toThrow();
159-
await expect(fs.stat(path.join(repoCloneIgnored, 'results'))).rejects.toThrow('ENOENT');
200+
await expect(
201+
fs.stat(path.join(requireCommitClone, 'committed-file.txt'))
202+
).resolves.not.toThrow();
203+
await expect(fs.stat(path.join(requireCommitClone, 'new-file.txt'))).resolves.not.toThrow();
204+
await expect(
205+
fs.stat(path.join(requireCommitClone, 'new-tracked-file.txt'))
206+
).resolves.not.toThrow();
160207
});
161208
});

packages/eas-cli/src/vcs/clients/git.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,19 @@ export default class GitClient extends Client {
182182
await setGitCaseSensitivityAsync(true, rootPath);
183183
await spawnAsync(
184184
'git',
185-
['clone', '--no-hardlinks', '--depth', '1', gitRepoUri, destinationPath],
185+
[
186+
'clone',
187+
// If we do not require a commit, we are going to later
188+
// copy the working directory into the destination path,
189+
// so we can skip the checkout step (which also adds files
190+
// that have been removed in the working directory).
191+
this.requireCommit ? null : '--no-checkout',
192+
'--no-hardlinks',
193+
'--depth',
194+
'1',
195+
gitRepoUri,
196+
destinationPath,
197+
].flatMap(e => e ?? []),
186198
{ cwd: rootPath }
187199
);
188200

0 commit comments

Comments
 (0)