Skip to content

Commit f4d5911

Browse files
committed
fix: skip stash when nothing to stash (fix #5)
1 parent 5de0643 commit f4d5911

File tree

5 files changed

+77
-45
lines changed

5 files changed

+77
-45
lines changed

lib/src/git.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Future<String> execGit(
4949
final result =
5050
await Process.run('git', gitArgs, workingDirectory: workingDirectory);
5151
if (result.exitCode != 0) {
52-
throw Exception(result.stderr);
52+
throw Exception('execGit ${result.stderr}');
5353
}
5454
String output = result.stdout as String;
5555
if (output.endsWith('\n')) {

lib/src/git_workflow.dart

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:io';
12
import 'dart:math';
23
import 'package:path/path.dart';
34
import 'package:verbose/verbose.dart';
@@ -33,7 +34,7 @@ List<String> processRenames(List<String> files,
3334
});
3435
}
3536

36-
const kStash = 'lint_staged automatic backup';
37+
const kStashMessage = 'lint_staged automatic backup';
3738

3839
const kMergeHead = 'MERGE_HEAD';
3940
const kMergeMode = 'MERGE_MODE';
@@ -107,8 +108,12 @@ class GitWorkflow {
107108
Future<String> getBackupStash(LintStagedContext ctx) async {
108109
final stashes =
109110
await execGit(['stash', 'list'], workingDirectory: workingDirectory);
111+
112+
if (stashes.isEmpty) {
113+
return '';
114+
}
110115
final index =
111-
stashes.split('\n').indexWhere((line) => line.contains(kStash));
116+
stashes.split('\n').indexWhere((line) => line.contains(kStashMessage));
112117
if (index == -1) {
113118
ctx.errors.add(kGetBackupStashError);
114119
throw Exception('lint_staged automatic backup is missing!');
@@ -255,14 +260,21 @@ class GitWorkflow {
255260
/// - git stash can't infer RD or MD states correctly, and will lose the deletion
256261
deletedFiles = await getDeletedFiles();
257262

258-
// Save stash of all staged files.
259-
// The `stash create` command creates a dangling commit without removing any files,
260-
// and `stash store` saves it as an actual stash.
261-
final hash = await execGit(['stash', 'create'],
262-
workingDirectory: workingDirectory);
263-
await execGit(['stash', 'store', '--quiet', '--message', kStash, hash],
263+
/// Save stash of all staged files.
264+
/// The `stash create` command creates a dangling commit without removing any files,
265+
/// and `stash store` saves it as an actual stash.
266+
final stash = await execGit(['stash', 'create'],
264267
workingDirectory: workingDirectory);
265268

269+
/// When there's nothing to stash, just skip.
270+
if (stash.isNotEmpty) {
271+
await execGit(
272+
['stash', 'store', '--quiet', '--message', kStashMessage, stash],
273+
workingDirectory: workingDirectory);
274+
} else {
275+
verbose('Nothing to stash.');
276+
}
277+
266278
verbose('Done backing up original state!');
267279
} catch (e) {
268280
handleError(e, ctx);
@@ -326,6 +338,8 @@ class GitWorkflow {
326338
} catch (applyError) {
327339
verbose('Error while restoring changes:');
328340
verbose(applyError.toString());
341+
verbose(
342+
'Content of file $unstagedPatch is:\n${File(unstagedPatch).readAsStringSync()}');
329343
verbose('Retrying with 3-way merge');
330344
try {
331345
// Retry with a 3-way merge if normal apply fails
@@ -368,6 +382,7 @@ class GitWorkflow {
368382

369383
verbose('Done restoring original state!');
370384
} catch (error) {
385+
verbose('Restoring original state error: $error');
371386
handleError(error, ctx, kRestoreOriginalStateError);
372387
}
373388
}
@@ -378,19 +393,25 @@ class GitWorkflow {
378393
Future<void> cleanup(LintStagedContext ctx) async {
379394
try {
380395
verbose('Dropping backup stash...');
381-
await execGit(['stash', 'drop', '--quiet', await getBackupStash(ctx)],
382-
workingDirectory: workingDirectory);
396+
final stash = await getBackupStash(ctx);
397+
if (stash.isNotEmpty) {
398+
await execGit([
399+
'stash',
400+
'drop',
401+
'--quiet',
402+
], workingDirectory: workingDirectory);
403+
}
383404
verbose('Done dropping backup stash!');
384405
} catch (error) {
385406
handleError(error, ctx);
386407
}
387408
}
388409

389410
void handleError(e, LintStagedContext ctx, [Symbol? symbol]) {
411+
verbose(StackTrace.current.toString());
390412
ctx.errors.add(kGitError);
391413
if (symbol != null) {
392414
ctx.errors.add(symbol);
393415
}
394-
// throw e;
395416
}
396417
}

lib/src/run.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,11 @@ Future<LintStagedContext> runAll({
113113
await git.hideUnstagedChanges(ctx);
114114
logger.success('Hiding unstaged changes to partially staged files...');
115115
}
116-
logger.progress('Running tasks for staged files...');
117-
await Future.wait(tasks.map((task) => task()));
118-
logger.success('Running tasks for staged files...');
116+
if (matchedFiles.isNotEmpty) {
117+
logger.progress('Running tasks for staged files...');
118+
await Future.wait(tasks.map((task) => task()));
119+
logger.success('Running tasks for staged files...');
120+
}
119121
if (!applyModifationsSkipped(ctx)) {
120122
logger.progress('Applying modifications from tasks...');
121123
await git.applyModifications(ctx);
@@ -126,6 +128,8 @@ Future<LintStagedContext> runAll({
126128
await git.resotreUnstagedChanges(ctx);
127129
logger.success('Restoring unstaged changes to partially staged files...');
128130
}
131+
verbose(
132+
'should restore origin state: ${restoreOriginalStateEnabled(ctx) && !restoreOriginalStateSkipped(ctx)}');
129133
if (restoreOriginalStateEnabled(ctx) && !restoreOriginalStateSkipped(ctx)) {
130134
logger.progress('Reverting to original state because of errors...');
131135
await git.restoreOriginState(ctx);
Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import 'dart:io';
2-
31
import 'package:lint_staged/src/file.dart';
42
import 'package:lint_staged/src/git.dart';
53
import 'package:path/path.dart' show join;
@@ -16,51 +14,51 @@ void main() {
1614
print('dir: ${project.dir}');
1715
await project.setup();
1816

17+
await project.writeFile('pubspec.yaml', kConfigFormatFix);
18+
await project.writeFile('lib/main.dart', kFormattedDart);
19+
await project.execGit(['add', '.']);
20+
await expectLater(
21+
project.gitCommit(gitCommitArgs: ['-m', 'committed pretty file']),
22+
completes);
23+
1924
// create a new repo for the git submodule to a temp path
20-
String submoduleDir = join(project.dir, 'submodule_temp');
21-
if (!await Directory(submoduleDir).exists()) {
22-
await Directory(submoduleDir).create(recursive: true);
23-
}
24-
await execGit(['init', submoduleDir]);
25-
await execGit(['config', 'user.name', '"test"'],
26-
workingDirectory: submoduleDir);
27-
await execGit(['config', 'user.email', '"[email protected]"'],
28-
workingDirectory: submoduleDir);
29-
await appendFile('README.md', '# Test\n', workingDirectory: submoduleDir);
30-
await execGit(['add', 'README.md'], workingDirectory: submoduleDir);
31-
await execGit(['commit', '-m initial commit'],
32-
workingDirectory: submoduleDir);
25+
final submoduleProject = IntegrationProject();
26+
await submoduleProject.setup();
3327

34-
// Add the newly-created repo as a submodule in a new path.
35-
// This simulates adding it from a remote. By default file protocol is not allowed,
36-
// see https://git-scm.com/docs/git-config#Documentation/git-config.txt-protocolallow
28+
/// Add the newly-created repo as a submodule in a new path.
29+
/// This simulates adding it from a remote. By default file protocol is not allowed,
30+
/// see https://git-scm.com/docs/git-config#Documentation/git-config.txt-protocolallow
3731
await project.execGit([
3832
'-c',
3933
'protocol.file.allow=always',
4034
'submodule',
4135
'add',
4236
'--force',
43-
'./submodule_temp',
37+
submoduleProject.dir,
4438
'./submodule',
4539
]);
46-
submoduleDir = join(project.dir, 'submodule');
47-
// Set these again for Windows git in CI
48-
await execGit(['config', 'user.name', '"test"'],
49-
workingDirectory: submoduleDir);
50-
await execGit(['config', 'user.email', '"[email protected]"'],
51-
workingDirectory: submoduleDir);
40+
41+
/// Commit this submodule
42+
await project.execGit(['add', '.']);
43+
await expectLater(
44+
project.gitCommit(
45+
allowEmpty: true, gitCommitArgs: ['-m', 'Add submodule']),
46+
completes);
47+
48+
final submoduleDir = join(project.dir, 'submodule');
5249
await writeFile('pubspec.yaml', kConfigFormatExit,
5350
workingDirectory: submoduleDir);
5451

55-
// Stage pretty file
52+
/// Stage pretty file
5653
await appendFile('lib/main.dart', kFormattedDart,
5754
workingDirectory: submoduleDir);
58-
await execGit(['add', 'lib/main.dart'], workingDirectory: submoduleDir);
55+
await execGit(['add', '.'], workingDirectory: submoduleDir);
5956

60-
// Run lint_staged with `dart format --set-exit-if-changed` and commit formatted file
61-
await project.gitCommit(workingDirectory: submoduleDir);
57+
/// Run lint_staged with `dart format --set-exit-if-changed` and commit formatted file
58+
await expectLater(
59+
project.gitCommit(workingDirectory: submoduleDir), completes);
6260

63-
// Nothing is wrong, so a new commit is created
61+
/// Nothing is wrong, so a new commit is created
6462
expect(
6563
await execGit(['rev-list', '--count', 'HEAD'],
6664
workingDirectory: submoduleDir),
@@ -71,6 +69,13 @@ void main() {
7169
contains('test'));
7270
expect(await readFile('lib/main.dart', workingDirectory: submoduleDir),
7371
equals(kFormattedDart));
72+
73+
/// Commit this submodule
74+
await project.execGit(['add', '.']);
75+
await expectLater(
76+
project.gitCommit(
77+
allowEmpty: true, gitCommitArgs: ['-m', 'Update submodule']),
78+
completes);
7479
});
7580
});
7681
}

test/integration/utils.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class IntegrationProject {
1111
: dir = join(Directory.systemTemp.path, 'tmp',
1212
'husky_test_${DateTime.now().microsecondsSinceEpoch}');
1313

14+
IntegrationProject.dirctory(this.dir);
15+
1416
Future<void> setup({bool initialCommit = true}) async {
1517
/// Git init
1618
await git.execGit(['init', dir]);

0 commit comments

Comments
 (0)