1{
2 lib,
3 stdenv,
4 common-updater-scripts,
5 coreutils,
6 gnugrep,
7 gnused,
8 nix,
9 writeScript,
10}:
11
12{
13 name ? null,
14 pname ? null,
15 version ? null,
16 attrPath ? null,
17 versionLister,
18 allowedVersions ? "",
19 ignoredVersions ? "",
20 rev-prefix ? "",
21 rev-suffix ? "",
22 odd-unstable ? false,
23 patchlevel-unstable ? false,
24}:
25
26let
27 # where to print git commands and debugging messages
28 fileForGitCommands = "update-git-commits.txt";
29
30 grep = lib.getExe gnugrep;
31 sed = lib.getExe gnused;
32
33 # shell script to update package
34 updateScript = writeScript "generic-update-script.sh" ''
35 #! ${stdenv.shell}
36 set -o errexit
37 set -x
38
39 name="$1"
40 pname="$2"
41 version="$3"
42 attr_path="$4"
43 version_lister="$5"
44 allowed_versions="$6"
45 ignored_versions="$7"
46 rev_prefix="$8"
47 rev_suffix="$9"
48 odd_unstable="''${10}"
49 patchlevel_unstable="''${11}"
50
51 [[ -n "$name" ]] || name="$UPDATE_NIX_NAME"
52 [[ -n "$pname" ]] || pname="$UPDATE_NIX_PNAME"
53 [[ -n "$version" ]] || version="$UPDATE_NIX_OLD_VERSION"
54 [[ -n "$attr_path" ]] || attr_path="$UPDATE_NIX_ATTR_PATH"
55
56 # print header
57 echo "# $name" >> ${fileForGitCommands}
58
59 function version_is_ignored() {
60 local tag="$1"
61 [ -n "$ignored_versions" ] && ${grep} -q -E -e "$ignored_versions" <<< "$tag"
62 }
63
64 function version_is_unstable() {
65 local tag="$1"
66 local enforce="$2"
67 if [ -n "$odd_unstable" -o -n "$enforce" ]; then
68 local minor=$(echo "$tag" | ${sed} -rne 's,^[0-9]+\.([0-9]+).*,\1,p')
69 if [ $((minor % 2)) -eq 1 ]; then
70 return 0
71 fi
72 fi
73 if [ -n "$patchlevel_unstable" -o -n "$enforce" ]; then
74 local patchlevel=$(echo "$tag" | ${sed} -rne 's,^[0-9]+\.[0-9]+\.([0-9]+).*$,\1,p')
75 if ((patchlevel >= 90)); then
76 return 0
77 fi
78 fi
79 return 1
80 }
81
82 tags=$(sh -c "$version_lister --pname=$pname --attr-path=$attr_path --file=\"${fileForGitCommands}\"") || exit 1
83
84 # print available tags
85 for tag in $tags; do
86 echo "# found $pname version: $tag" >> ${fileForGitCommands}
87 done
88
89 # cut any revision prefix not used in the NixOS package version
90 if [ -n "$rev_prefix" ]; then
91 tags=$(echo "$tags" | ${grep} "^$rev_prefix")
92 tags=$(echo "$tags" | ${sed} -e "s,^$rev_prefix,,")
93 fi
94 # cut any revision suffix not used in the NixOS package version
95 if [ -n "$rev_suffix" ]; then
96 tags=$(echo "$tags" | ${grep} -- "$rev_suffix$")
97 tags=$(echo "$tags" | ${sed} -e "s,$rev_suffix\$,,")
98 fi
99 tags=$(echo "$tags" | ${grep} "^[0-9]")
100 if [ -n "$allowed_versions" ]; then
101 tags=$(echo "$tags" | ${grep} -E -e "$allowed_versions")
102 fi
103
104 # sort the tags in decreasing order
105 tags=$(echo "$tags" | ${coreutils}/bin/sort --reverse --version-sort)
106
107 # find the newest tag
108 # do not consider development versions
109 for latest_tag in $tags; do
110 if version_is_ignored "$latest_tag"; then
111 echo "# skip ignored version: $pname-$latest_tag" >> ${fileForGitCommands}
112 latest_tag=
113 elif version_is_unstable "$latest_tag"; then
114 echo "# skip development version: $pname-$latest_tag" >> ${fileForGitCommands}
115 latest_tag=
116 else
117 if version_is_unstable "$latest_tag" "enforce"; then
118 echo "# use potential development version: $pname-$latest_tag" >> ${fileForGitCommands}
119 fi
120 break
121 fi
122 done
123
124 if [ -n "$latest_tag" ]; then
125 # print commands to commit the changes
126 if [ "$version" != "$latest_tag" ]; then
127 pfile=$(EDITOR=echo ${nix}/bin/nix edit --extra-experimental-features nix-command -f. "$attr_path")
128 echo " git add $pfile " >> ${fileForGitCommands}
129 echo " git commit -m '$attr_path: $version -> $latest_tag'" >> ${fileForGitCommands}
130 fi
131
132 # update the nix expression
133 ${common-updater-scripts}/bin/update-source-version --print-changes "$attr_path" "$latest_tag"
134 else
135 # No changes for commit protocol.
136 echo "[]"
137 fi
138
139 echo "" >> ${fileForGitCommands}
140 '';
141
142in
143{
144 name = "generic-update-script";
145 command = [
146 updateScript
147 name
148 pname
149 version
150 attrPath
151 versionLister
152 allowedVersions
153 ignoredVersions
154 rev-prefix
155 rev-suffix
156 odd-unstable
157 patchlevel-unstable
158 ];
159 supportedFeatures = [
160 # Stdout must contain output according to the updateScript commit protocol when the update script finishes with a non-zero exit code.
161 "commit"
162 ];
163}