@kova1/pullr 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +29 -26
  2. package/bin/pullr +9 -4
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -12,7 +12,7 @@ everything current means `cd`-ing into each one.
12
12
 
13
13
  ```console
14
14
  $ pullr ~/work
15
- + api (main, 3 new commit(s))
15
+ + api (main, 3 new commits)
16
16
  = web (main)
17
17
  - scratch (main has no upstream)
18
18
  x infra (main)
@@ -32,6 +32,12 @@ brew install kova1max/tap/pullr
32
32
  npm install -g @kova1/pullr
33
33
  ```
34
34
 
35
+ To try it without installing anything:
36
+
37
+ ```sh
38
+ npx @kova1/pullr --dry-run ~/work
39
+ ```
40
+
35
41
  Or copy [`bin/pullr`](bin/pullr) anywhere on your `PATH` - it is a single bash
36
42
  script with no dependencies beyond `git`.
37
43
 
@@ -40,6 +46,24 @@ Every release is also mirrored to
40
46
  `@kova1max/pullr` (GitHub requires the repo owner as scope). Installing from
41
47
  there needs a GitHub token, so the npm registry above is the easier choice.
42
48
 
49
+ ## What it will never do
50
+
51
+ pullr is built to be safe to run across a whole workspace without looking
52
+ first. It will never:
53
+
54
+ - **Create a merge commit.** Pulls are fast-forward only.
55
+ - **Touch a branch that has diverged** from its upstream. It is reported as
56
+ failed and left exactly as it was. Rebasing it is opt-in with `--rebase`,
57
+ and a rebase that hits a conflict is aborted, leaving the repository as it
58
+ was.
59
+ - **Stash or discard your changes.** There is no auto-stash; if git refuses
60
+ to update a dirty working tree, the repository is reported as failed.
61
+ - **Touch a repository on a detached `HEAD`**, or a branch with no upstream.
62
+ Both are skipped.
63
+ - **Enter a nested repository.** Repositories inside another repository,
64
+ including submodules, are left to their parent.
65
+ - **Follow symlinked directories.**
66
+
43
67
  ## Usage
44
68
 
45
69
  ```
@@ -53,25 +77,15 @@ pullr [options] [DIR]
53
77
  | `--max-depth N` | `2` | How many directory levels below `DIR` to search. `0` = only `DIR` itself, `1` = `DIR` and its direct children, ... |
54
78
  | `-n`, `--dry-run` | | Show what a run would do without pulling, see below |
55
79
  | `-r`, `--rebase` | off | Rebase local commits onto the upstream instead of refusing a diverged branch (`git pull --rebase`). A rebase that hits a conflict is aborted and the repository is left as it was. |
80
+ | `--no-color` | | Disable colored output. Also disabled when the [`NO_COLOR`](https://no-color.org) environment variable is set, or when output is not a terminal. |
56
81
  | `-V`, `--version` | | Print the version |
57
82
  | `-h`, `--help` | | Show help |
58
83
 
59
- Behaviour:
60
-
61
- - Runs `git pull --ff-only`, so it never creates merge commits. A branch that
62
- has diverged from its upstream is reported as failed and left untouched.
63
- With `--rebase`, that branch's local commits are rebased onto the upstream
64
- instead, and the line reads `+ api (main, 3 new commits, 2 rebased)`. There
65
- is no auto-stash: a dirty tree makes git refuse the rebase, which is
66
- reported as failed.
67
- - Does not descend into a repository once found - nested repositories and
68
- submodules are left to their parent.
69
- - Skips repositories on a detached `HEAD` and branches with no upstream.
70
- - Does not follow symlinked directories.
71
- - Exits `1` if any pull failed, `2` on invalid arguments, `0` otherwise.
84
+ ### Output
72
85
 
73
86
  Each repository gets one line: `+` updated, `=` already up to date, `-`
74
- skipped, `x` failed (with git's output indented below it).
87
+ skipped, `x` failed (with git's output indented below it). Exits `1` if any
88
+ pull failed, `2` on invalid arguments, `0` otherwise.
75
89
 
76
90
  ### Dry run
77
91
 
@@ -97,17 +111,6 @@ remote as it is now, then prints the same lines a real run would (with
97
111
  only updates remote-tracking refs: the working tree and current branch are
98
112
  never modified. Exit codes match a real run.
99
113
 
100
- ## Development
101
-
102
- ```sh
103
- npm install # installs bats
104
- npm test # end-to-end tests against real temporary git repos
105
- npm run lint # shellcheck
106
- PULLR_BASH=/bin/bash npm test # run the suite under macOS's bash 3.2
107
- ```
108
-
109
- Releases are cut by GitHub Actions - see [RELEASE.md](RELEASE.md).
110
-
111
114
  ## License
112
115
 
113
116
  [MIT](LICENSE)
package/bin/pullr CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env bash
2
2
  # Recursively find git repos under a directory and fast-forward pull each one.
3
- # Usage: pullr [--jobs N] [--max-depth N] [--dry-run] [--rebase] [DIR]
3
+ # Usage: pullr [--jobs N] [--max-depth N] [--dry-run] [--rebase] [--no-color] [DIR]
4
4
  set -euo pipefail
5
5
 
6
- VERSION="0.3.1" # set by the release workflow
6
+ VERSION="0.4.0" # set by the release workflow
7
7
 
8
8
  usage() {
9
9
  cat <<'EOF'
@@ -24,6 +24,8 @@ Options:
24
24
  refusing a branch that has diverged (git pull --rebase).
25
25
  A rebase that hits a conflict is aborted, leaving the
26
26
  repository as it was.
27
+ --no-color Disable colored output. Also disabled when NO_COLOR is
28
+ set (https://no-color.org) or output is not a terminal.
27
29
  -V, --version Print the version.
28
30
  -h, --help Show this help.
29
31
  EOF
@@ -32,6 +34,7 @@ EOF
32
34
  mode=pull
33
35
  jobs=4
34
36
  rebase=0
37
+ color=1
35
38
  max_depth=2
36
39
  root=""
37
40
 
@@ -43,6 +46,7 @@ while (($#)); do
43
46
  --max-depth=*) max_depth="${1#*=}"; shift ;;
44
47
  -n|--dry-run) mode=dryrun; shift ;;
45
48
  -r|--rebase) rebase=1; shift ;;
49
+ --no-color) color=0; shift ;;
46
50
  -h|--help) usage; exit 0 ;;
47
51
  -V|--version) echo "pullr $VERSION"; exit 0 ;;
48
52
  -*) echo "Unknown option: $1" >&2; usage >&2; exit 2 ;;
@@ -58,7 +62,8 @@ root="${root:-.}"
58
62
  [[ -d "$root" ]] || { echo "Not a directory: $root" >&2; exit 2; }
59
63
  root="$(cd "$root" && pwd)"
60
64
 
61
- if [[ -t 1 ]]; then
65
+ # https://no-color.org: any non-empty NO_COLOR disables color
66
+ if [[ "$color" == 1 && -z "${NO_COLOR:-}" && -t 1 ]]; then
62
67
  green=$'\e[32m' yellow=$'\e[33m' red=$'\e[31m' dim=$'\e[2m' reset=$'\e[0m'
63
68
  else
64
69
  green="" yellow="" red="" dim="" reset=""
@@ -121,7 +126,7 @@ pull_repo() {
121
126
  "$(update_note "$n" "$local_n" rebased)" "$reset"
122
127
  }
123
128
 
124
- # "N new commit(s)[, M rebased|to rebase]"
129
+ # "N new commits[, M rebased|to rebase]", singular when N is 1
125
130
  update_note() {
126
131
  local n="$1" local_n="$2" verb="$3" note
127
132
  note="$n new commit$([[ "$n" == 1 ]] || printf s)"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kova1/pullr",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Fast-forward pull every git repository under a directory",
5
5
  "keywords": [
6
6
  "git",