| 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='Test workflows involving pull request.' |
| 4 | |
| 5 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
| 6 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
| 7 | |
| 8 | . ./test-lib.sh |
| 9 | |
| 10 | test_expect_success 'setup' ' |
| 11 | |
| 12 | git init --bare upstream.git && |
| 13 | git init --bare downstream.git && |
| 14 | git clone upstream.git upstream-private && |
| 15 | git clone downstream.git local && |
| 16 | |
| 17 | trash_url="file://$TRASH_DIRECTORY" && |
| 18 | downstream_url="$trash_url/downstream.git/" && |
| 19 | upstream_url="$trash_url/upstream.git/" && |
| 20 | |
| 21 | ( |
| 22 | cd upstream-private && |
| 23 | cat <<-\EOT >mnemonic.txt && |
| 24 | Thirtey days hath November, |
| 25 | Aprile, June, and September: |
| 26 | EOT |
| 27 | git add mnemonic.txt && |
| 28 | test_tick && |
| 29 | git commit -m "\"Thirty days\", a reminder of month lengths" && |
| 30 | git tag -m "version 1" -a initial && |
| 31 | git push --tags origin main |
| 32 | ) && |
| 33 | ( |
| 34 | cd local && |
| 35 | git remote add upstream "$trash_url/upstream.git" && |
| 36 | git fetch upstream && |
| 37 | git pull upstream main && |
| 38 | cat <<-\EOT >>mnemonic.txt && |
| 39 | Of twyecescore-eightt is but eine, |
| 40 | And all the remnante be thrycescore-eine. |
| 41 | O’course Leap yare comes an’pynes, |
| 42 | Ev’rie foure yares, gote it ryghth. |
| 43 | An’twyecescore-eight is but twyecescore-nyne. |
| 44 | EOT |
| 45 | git add mnemonic.txt && |
| 46 | test_tick && |
| 47 | git commit -m "More detail" && |
| 48 | git tag -m "version 2" -a full && |
| 49 | git checkout -b simplify HEAD^ && |
| 50 | mv mnemonic.txt mnemonic.standard && |
| 51 | cat <<-\EOT >mnemonic.clarified && |
| 52 | Thirty days has September, |
| 53 | All the rest I can’t remember. |
| 54 | EOT |
| 55 | git add -N mnemonic.standard mnemonic.clarified && |
| 56 | git commit -a -m "Adapt to use modern, simpler English |
| 57 | |
| 58 | But keep the old version, too, in case some people prefer it." && |
| 59 | git checkout main |
| 60 | ) |
| 61 | |
| 62 | ' |
| 63 | |
| 64 | test_expect_success 'setup: two scripts for reading pull requests' ' |
| 65 | |
| 66 | downstream_url_for_sed=$( |
| 67 | printf "%s\n" "$downstream_url" | |
| 68 | sed -e '\''s/\\/\\\\/g'\'' -e '\''s/[[/.*^$]/\\&/g'\'' |
| 69 | ) && |
| 70 | |
| 71 | cat <<-\EOT >read-request.sed && |
| 72 | #!/bin/sed -nf |
| 73 | # Note that a request could ask for "tag $tagname" |
| 74 | / in the Git repository at:$/!d |
| 75 | n |
| 76 | /^$/ n |
| 77 | s/ tag \([^ ]*\)$/ tag--\1/ |
| 78 | s/^[ ]*\(.*\) \([^ ]*\)/please pull\ |
| 79 | \1\ |
| 80 | \2/p |
| 81 | q |
| 82 | EOT |
| 83 | |
| 84 | cat <<-EOT >fuzz.sed |
| 85 | #!/bin/sed -nf |
| 86 | s/$downstream_url_for_sed/URL/g |
| 87 | s/$OID_REGEX/OBJECT_NAME/g |
| 88 | s/A U Thor/AUTHOR/g |
| 89 | s/[-0-9]\{10\} [:0-9]\{8\} [-+][0-9]\{4\}/DATE/g |
| 90 | s/ [^ ].*/ SUBJECT/g |
| 91 | s/ [^ ].* (DATE)/ SUBJECT (DATE)/g |
| 92 | s|tags/full|BRANCH|g |
| 93 | s/mnemonic.txt/FILENAME/g |
| 94 | s/^version [0-9]/VERSION/ |
| 95 | /^ FILENAME | *[0-9]* [-+]*\$/ b diffstat |
| 96 | /^AUTHOR ([0-9]*):\$/ b shortlog |
| 97 | p |
| 98 | b |
| 99 | : diffstat |
| 100 | n |
| 101 | / [0-9]* files* changed/ { |
| 102 | a\\ |
| 103 | DIFFSTAT |
| 104 | b |
| 105 | } |
| 106 | b diffstat |
| 107 | : shortlog |
| 108 | /^ [a-zA-Z]/ n |
| 109 | /^[a-zA-Z]* ([0-9]*):\$/ n |
| 110 | /^\$/ N |
| 111 | /^\n[a-zA-Z]* ([0-9]*):\$/!{ |
| 112 | a\\ |
| 113 | SHORTLOG |
| 114 | D |
| 115 | } |
| 116 | n |
| 117 | b shortlog |
| 118 | EOT |
| 119 | |
| 120 | ' |
| 121 | |
| 122 | test_expect_success 'pull request when forgot to push' ' |
| 123 | |
| 124 | rm -fr downstream.git && |
| 125 | git init --bare downstream.git && |
| 126 | ( |
| 127 | cd local && |
| 128 | git checkout initial && |
| 129 | git merge --ff-only main && |
| 130 | test_must_fail git request-pull initial "$downstream_url" \ |
| 131 | 2>../err |
| 132 | ) && |
| 133 | test_grep "No match for commit .*" err && |
| 134 | test_grep "Are you sure you pushed" err |
| 135 | |
| 136 | ' |
| 137 | |
| 138 | test_expect_success 'pull request after push' ' |
| 139 | |
| 140 | rm -fr downstream.git && |
| 141 | git init --bare downstream.git && |
| 142 | ( |
| 143 | cd local && |
| 144 | git checkout initial && |
| 145 | git merge --ff-only main && |
| 146 | git push origin main:for-upstream && |
| 147 | git request-pull initial origin main:for-upstream >../request |
| 148 | ) && |
| 149 | sed -nf read-request.sed <request >digest && |
| 150 | { |
| 151 | read task && |
| 152 | read repository && |
| 153 | read branch |
| 154 | } <digest && |
| 155 | ( |
| 156 | cd upstream-private && |
| 157 | git checkout initial && |
| 158 | git pull --ff-only "$repository" "$branch" |
| 159 | ) && |
| 160 | test "$branch" = for-upstream && |
| 161 | test_cmp local/mnemonic.txt upstream-private/mnemonic.txt |
| 162 | |
| 163 | ' |
| 164 | |
| 165 | test_expect_success 'request asks HEAD to be pulled' ' |
| 166 | |
| 167 | rm -fr downstream.git && |
| 168 | git init --bare downstream.git && |
| 169 | ( |
| 170 | cd local && |
| 171 | git checkout initial && |
| 172 | git merge --ff-only main && |
| 173 | git push --tags origin main simplify && |
| 174 | git push origin main:for-upstream && |
| 175 | git request-pull initial "$downstream_url" >../request |
| 176 | ) && |
| 177 | sed -nf read-request.sed <request >digest && |
| 178 | { |
| 179 | read task && |
| 180 | read repository && |
| 181 | read branch |
| 182 | } <digest && |
| 183 | test -z "$branch" |
| 184 | |
| 185 | ' |
| 186 | |
| 187 | test_expect_success 'pull request format' ' |
| 188 | |
| 189 | rm -fr downstream.git && |
| 190 | git init --bare downstream.git && |
| 191 | cat <<-\EOT >expect && |
| 192 | The following changes since commit OBJECT_NAME: |
| 193 | |
| 194 | SUBJECT (DATE) |
| 195 | |
| 196 | are available in the Git repository at: |
| 197 | |
| 198 | URL BRANCH |
| 199 | |
| 200 | for you to fetch changes up to OBJECT_NAME: |
| 201 | |
| 202 | SUBJECT (DATE) |
| 203 | |
| 204 | ---------------------------------------------------------------- |
| 205 | VERSION |
| 206 | |
| 207 | ---------------------------------------------------------------- |
| 208 | SHORTLOG |
| 209 | |
| 210 | DIFFSTAT |
| 211 | EOT |
| 212 | ( |
| 213 | cd local && |
| 214 | git checkout initial && |
| 215 | git merge --ff-only main && |
| 216 | git push origin tags/full && |
| 217 | git request-pull initial "$downstream_url" tags/full >../request |
| 218 | ) && |
| 219 | <request sed -nf fuzz.sed >request.fuzzy && |
| 220 | test_cmp expect request.fuzzy && |
| 221 | |
| 222 | ( |
| 223 | cd local && |
| 224 | git request-pull initial "$downstream_url" tags/full:refs/tags/full |
| 225 | ) >request && |
| 226 | sed -nf fuzz.sed <request >request.fuzzy && |
| 227 | test_cmp expect request.fuzzy && |
| 228 | |
| 229 | ( |
| 230 | cd local && |
| 231 | git request-pull initial "$downstream_url" full |
| 232 | ) >request && |
| 233 | test_grep " tags/full\$" request |
| 234 | ' |
| 235 | |
| 236 | test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' ' |
| 237 | |
| 238 | ( |
| 239 | cd local && |
| 240 | OPTIONS_KEEPDASHDASH=Yes && |
| 241 | export OPTIONS_KEEPDASHDASH && |
| 242 | git checkout initial && |
| 243 | git merge --ff-only main && |
| 244 | git push origin main:for-upstream && |
| 245 | git request-pull -- initial "$downstream_url" main:for-upstream >../request |
| 246 | ) |
| 247 | |
| 248 | ' |
| 249 | |
| 250 | test_expect_success 'request-pull quotes regex metacharacters properly' ' |
| 251 | |
| 252 | rm -fr downstream.git && |
| 253 | git init --bare downstream.git && |
| 254 | ( |
| 255 | cd local && |
| 256 | git checkout initial && |
| 257 | git merge --ff-only main && |
| 258 | git tag -mrelease v2.0 && |
| 259 | git push origin refs/tags/v2.0:refs/tags/v2-0 && |
| 260 | test_must_fail git request-pull initial "$downstream_url" tags/v2.0 \ |
| 261 | 2>../err |
| 262 | ) && |
| 263 | test_grep "No match for commit .*" err && |
| 264 | test_grep "Are you sure you pushed" err |
| 265 | |
| 266 | ' |
| 267 | |
| 268 | test_expect_success 'pull request with mismatched object' ' |
| 269 | |
| 270 | rm -fr downstream.git && |
| 271 | git init --bare downstream.git && |
| 272 | ( |
| 273 | cd local && |
| 274 | git checkout initial && |
| 275 | git merge --ff-only main && |
| 276 | git push origin HEAD:refs/tags/full && |
| 277 | test_must_fail git request-pull initial "$downstream_url" tags/full \ |
| 278 | 2>../err |
| 279 | ) && |
| 280 | test_grep "points to a different object" err && |
| 281 | test_grep "Are you sure you pushed" err |
| 282 | |
| 283 | ' |
| 284 | |
| 285 | test_expect_success 'pull request with stale object' ' |
| 286 | |
| 287 | rm -fr downstream.git && |
| 288 | git init --bare downstream.git && |
| 289 | ( |
| 290 | cd local && |
| 291 | git checkout initial && |
| 292 | git merge --ff-only main && |
| 293 | git push origin refs/tags/full && |
| 294 | git tag -f -m"Thirty-one days" full && |
| 295 | test_must_fail git request-pull initial "$downstream_url" tags/full \ |
| 296 | 2>../err |
| 297 | ) && |
| 298 | test_grep "points to a different object" err && |
| 299 | test_grep "Are you sure you pushed" err |
| 300 | |
| 301 | ' |
| 302 | |
| 303 | test_done |