lint_staged

Last updated:

0 purchases

lint_staged Image
lint_staged Images
Add to Cart

Description:

lint staged

lint_staged #




Run linters on git staged files for your Flutter and Dart projects.
Inspired by Javascript lint-staged
Why #
Linting makes more sense when run before committing your code. By doing so you can ensure no errors go into the repository and enforce code style. But running a lint process on a whole project is slow, and linting results can be irrelevant. Ultimately you only want to lint files that will be committed.
This project contains a script that will run arbitrary shell tasks with a list of staged files as an argument, filtered by a specified glob pattern.
Installation and setup #
To install lint_staged in the recommended way, you need to:

Install lint_staged itself:

dart pub add --dev lint_staged


Set up the pre-commit git hook to run lint_staged

Husky is a recommended choice for configuring git hooks
Read more about git hooks here


Configure lint_staged to run linters and other tasks:

for example, add following in pubspec.yaml:

lint_staged:
'lib/**.dart': dart format --fix && dart fix --apply
copied to clipboard
to automatically format & fix all staged dart files.

See Configuration for more info



Don't forget to commit changes to pubspec.yaml and .husky to share this setup with your team!
Now change a few files, git add or git add --patch some of them to your commit, and try to git commit them.
See examples and configuration for more information.
Changelog #
See CHANGELOG.md.
Command line flags #
❯ dart lint_staged --help
Usage: lint_staged [options]

Options:
--allow-empty allow empty commits when tasks revert all staged changes (default: false)
--diff [string] override the default "--staged" flag of "git diff" to get list of files. Implies
"--no-stash".
--diff-filter [string] override the default "--diff-filter=ACMR" flag of "git diff" to get list of files
--no-stash disable the backup stash, and do not revert in case of errors
copied to clipboard

--allow-empty: By default, when linter tasks undo all staged changes, lint_staged will exit with an error and abort the commit. Use this flag to allow creating empty git commits.
--diff: By default linters are filtered against all files staged in git, generated from git diff --staged. This option allows you to override the --staged flag with arbitrary revisions. For example to get a list of changed files between two branches, use --diff="branch1...branch2". You can also read more from about git diff and gitrevisions. This option also implies --no-stash.
--diff-filter: By default only files that are added, copied, modified, or renamed are included. Use this flag to override the default ACMR value with something else: added (A), copied (C), deleted (D), modified (M), renamed (R), type changed (T), unmerged (U), unknown (X), or pairing broken (B). See also the git diff docs for --diff-filter.
--no-stash: By default a backup stash will be created before running the tasks, and all task modifications will be reverted in case of an error. This option will disable creating the stash, and instead leave all modifications in the index when aborting the commit. Can be re-enabled with --stash

Configuration #
Lint_staged must be configured in your pubspec.yaml
pubspec.yaml example:
lint_staged:
'lib/**.dart': your-cmd
copied to clipboard
This config will execute your-cmd with staged dart files passed as arguments.
Filtering files #
Linter commands work on a subset of all staged files, defined by a glob pattern. lint_staged uses glob for matching files with the following syntax:
Match any characters in a filename: * #
The * character matches zero or more of any character other than /. This
means that it can be used to match all files in a given directory that match a
pattern without also matching files in a subdirectory. For example, lib/*.dart
will match lib/glob.dart but not lib/src/utils.dart.
Match any characters across directories: ** #
** is like *, but matches / as well. It's useful for matching files or
listing directories recursively. For example, lib/**.dart will match both
lib/glob.dart and lib/src/utils.dart.
If ** appears at the beginning of a glob, it won't match absolute paths or
paths beginning with ../. For example, **.dart won't match /foo.dart,
although /**.dart will. This is to ensure that listing a bunch of paths and
checking whether they match a glob produces the same results as listing that
glob. In the previous example, /foo.dart wouldn't be listed for **.dart, so
it shouldn't be matched by it either.
This is an extension to Bash glob syntax that's widely supported by other glob
implementations.
Match any single character: ? #
The ? character matches a single character other than /. Unlike *, it
won't match any more or fewer than one character. For example, test?.dart will
match test1.dart but not test10.dart or test.dart.
Match a range of characters: [...] #
The [...] construction matches one of several characters. It can contain
individual characters, such as [abc], in which case it will match any of those
characters; it can contain ranges, such as [a-zA-Z], in which case it will
match any characters that fall within the range; or it can contain a mix of
both. It will only ever match a single character. For example,
test[a-zA-Z_].dart will match testx.dart, testA.dart, and test_.dart,
but not test-.dart.
If it starts with ^ or !, the construction will instead match all characters
not mentioned. For example, test[^a-z].dart will match test1.dart but not
testa.dart.
This construction never matches /.
Match one of several possibilities: {...,...} #
The {...,...} construction matches one of several options, each of which is a
glob itself. For example, lib/{*.dart,src/*} matches lib/glob.dart and
lib/src/data.txt. It can contain any number of options greater than one, and
can even contain nested options.
This is an extension to Bash glob syntax, although it is supported by other
layers of Bash and is often used in conjunction with globs.
Escaping a character: \ #
The \ character can be used in any context to escape a character that would
otherwise be semantically meaningful. For example, \*.dart matches *.dart
but not test.dart.
Syntax errors #
Because they're used as part of the shell, almost all strings are valid Bash
globs. This implementation is more picky, and performs some validation to ensure
that globs are meaningful. For instance, unclosed { and [ are disallowed.
Reserved syntax: (...) #
Parentheses are reserved in case this package adds support for Bash extended
globbing in the future. For the time being, using them will throw an error
unless they're escaped.
Exclude pattern: ! #
For any files you wish to exclude, use the same glob pattern but prepend it with !
lint_staged:
'lib/**.dart': your-cmd
'!lib/**.g.dart': your-cmd
copied to clipboard
This would include all .dart files, but exclude .g.dart files.
What commands are supported? #
Supported are any executables installed locally or globally via pub as well as any executable from your $PATH.

Using globally installed scripts is discouraged, since lint_staged may not work for someone who doesn't have it installed.

lint_staged uses Process.run to locate locally installed scripts.
Pass arguments to your commands separated by space as you would do in the shell. See examples below.
Running multiple commands in a sequence #
You can run multiple commands in a sequence on every glob. To do so, pass a list of commands joined with &&. This is useful for running autoformatting tools like dart format or dart analyze but can be used for any arbitrary sequences.
For example:
lint_staged:
'lib/**.dart': dart format --fix && dart fix --apply
copied to clipboard
going to execute dart format --fix and if it exits with 0 code, it will execute dart fix --apply on all staged dart files.
Examples #
All examples assume you've already set up lint_staged in the pubspec.yaml file and husky in its own config file.
lint_staged:
copied to clipboard
In .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"

dart run lint_staged
copied to clipboard
Note: we don't pass a path as an argument for the runners. This is important since lint_staged will do this for you.
Automatically fix analyze issues for .dart running as a pre-commit hook #

Click to expand
lint_staged:
'lib/**.dart': dart fix --apply
copied to clipboard

Automatically fix code format and add to commit #

Click to expand
lint_staged:
'lib/**.dart': dart format --fix
copied to clipboard
This will run dart format --fix and automatically add changes to the commit.

Frequently Asked Questions #
Can I use lint_staged via dart code? #

Click to expand
Yes!
import 'package:lint_staged/lint_staged.dart';

try {
final success = await lintStaged()
print(success ? 'Linting was successful!' : 'Linting failed!')
} catch (e) {
print(e);
}
copied to clipboard
Parameters to lintStaged are equivalent to their CLI counterparts:
const success = await lintStaged({
allowEmpty: false,
stash: true,
})
copied to clipboard

Using with JetBrains IDEs (WebStorm, PyCharm, IntelliJ IDEA, RubyMine, etc.) #

Click to expand
Update: The latest version of JetBrains IDEs now support running hooks as you would expect.
When using the IDE's GUI to commit changes with the precommit hook, you might see inconsistencies in the IDE and command line. This is known issue at JetBrains so if you want this fixed, please vote for it on YouTrack.
Until the issue is resolved in the IDE, you can use the following config to work around it:
{
"husky": {
"hooks": {
"pre-commit": "lint_staged",
"post-commit": "git update-index --again"
}
}
}
copied to clipboard
Thanks to this comment for the fix!

Can I run lint_staged in CI, or when there are no staged files? #

Click to expand
Lint_staged will by default run against files staged in git, and should be run during the git pre-commit hook, for example. It's also possible to override this default behaviour and run against files in a specific diff, for example
all changed files between two different branches. If you want to run lint_staged in the CI, maybe you can set it up to compare the branch in a Pull Request/Merge Request to the target branch.
Try out the git diff command until you are satisfied with the result, for example:
git diff --diff-filter=ACMR --name-only master...my-branch
copied to clipboard
This will print a list of added, changed, modified, and renamed files between master and my-branch.
You can then run lint_staged against the same files with:
dart run lint_staged --diff="master...my-branch"
copied to clipboard

The output of commit hook looks weird (no colors, duplicate lines, verbose output on Windows, …) #

Click to expand
Git 2.36.0 introduced a change to hooks where they were no longer run in the original TTY.
This was fixed in 2.37.0:
https://raw.githubusercontent.com/git/git/master/Documentation/RelNotes/2.37.0.txt


In Git 2.36 we revamped the way how hooks are invoked. One change
that is end-user visible is that the output of a hook is no longer
directly connected to the standard output of "git" that spawns the
hook, which was noticed post release. This is getting corrected.
(merge a082345372 ab/hooks-regression-fix later to maint).


If updating Git doesn't help, you can try to manually redirect the output in your Git hook; for example:
# .husky/pre-commit

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

if sh -c ": >/dev/tty" >/dev/null 2>/dev/null; then exec >/dev/tty 2>&1; fi

dart run lint_staged
copied to clipboard

License:

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Customer Reviews

There are no reviews.