Browse code

Cherry-pick helper

Clayton Coleman authored on 2015/10/04 03:37:52
Showing 3 changed files
... ...
@@ -176,6 +176,36 @@ OpenShift is checked into this repository.  To install `godep` locally run:
176 176
 
177 177
 If you are not updating packages you should not need godep installed.
178 178
 
179
+## Cherry-picking an upstream commit into Origin
180
+
181
+You can use `hack/cherry-pick.sh` to generate patches for Origin from upstream commits. To use
182
+this command, be sure to setup remote branches like https://gist.github.com/piscisaureus/3342247
183
+so that `git show origin/pr/<number>` displays information about your branch after a `git fetch`.
184
+You must also have the Kubernetes repository checked out in your GOPATH (visible as `../../../k8s.io/kubernetes`)
185
+and have no modified or uncommited files in either repository.
186
+
187
+To pull an upstream commit, run:
188
+
189
+    $ hack/cherry-pick.sh <pr_number>
190
+
191
+This will attempt to create a patch from the current Kube rebase version in Origin that contains
192
+the commits added in the PR. If the PR has already been merged to the Kube version, you'll get an
193
+error. If there are conflicts, you'll have to resolve them in the upstream repo, then hit ENTER
194
+to continue. The end result will be a single commit in your Origin repo that contains the changes.
195
+
196
+If you want to run without a rebase option, set `NO_REBASE=1` before the command is run. You can
197
+also specify a commit range directly with:
198
+
199
+    $ hack/cherry-pick.sh origin/master...<some_branch>
200
+
201
+All upstream commits should have a commit message where the first line is:
202
+
203
+    UPSTREAM: <PR number|drop|carry>: <short description>
204
+
205
+`drop` indicates the commit should be removed during the next rebase. `carry` means that the change
206
+cannot go into upstream, and we should continue to use it during the next rebase.
207
+
208
+
179 209
 ## Updating Kubernetes from upstream
180 210
 
181 211
 There are a few steps involved in rebasing Origin to a new version of Kubernetes. We need to make sure
182 212
new file mode 100755
... ...
@@ -0,0 +1,83 @@
0
+#!/bin/bash
1
+
2
+# See HACKING.md for usage
3
+
4
+set -o errexit
5
+set -o nounset
6
+set -o pipefail
7
+
8
+OS_ROOT=$(dirname "${BASH_SOURCE}")/..
9
+source "${OS_ROOT}/hack/common.sh"
10
+source "${OS_ROOT}/hack/util.sh"
11
+os::log::install_errexit
12
+
13
+# Go to the top of the tree.
14
+cd "${OS_ROOT}"
15
+
16
+if [[ "$#" -ne 1 ]]; then
17
+  echo "You must supply a pull request by number or a Git range in the upstream Kube project" 1>&2
18
+  exit 1
19
+fi
20
+os::build::require_clean_tree # Origin tree must be clean
21
+
22
+patch="${TMPDIR}/patch"
23
+kubedir="../../../k8s.io/kubernetes"
24
+if [[ ! -d "${kubedir}" ]]; then
25
+  echo "Expected ${kubedir} to exist" 1>&2
26
+  exit 1
27
+fi
28
+
29
+if [[ -z "${NO_REBASE-}" ]]; then
30
+  lastkube="$(go run ${OS_ROOT}/hack/version.go ${OS_ROOT}/Godeps/Godeps.json k8s.io/kubernetes/pkg/api)"
31
+fi
32
+
33
+pushd "${kubedir}" > /dev/null
34
+os::build::require_clean_tree
35
+git fetch
36
+
37
+selector="$(os::build::commit_range $1 origin/master)"
38
+
39
+if [[ -z "${NO_REBASE-}" ]]; then
40
+  echo "++ Generating patch for ${selector} onto ${lastkube} ..." 2>&1
41
+  if git rev-parse kube_rebaser_branch > /dev/null 2>&1; then
42
+    git branch -d kube_rebaser_branch
43
+  fi
44
+  git checkout -b kube_rebaser_branch "${lastkube}"
45
+  git diff -p --raw "${selector}" > "${patch}"
46
+  if ! git apply -3 "${patch}"; then
47
+    git rerere # record pre state
48
+    echo 2>&1
49
+    echo "++ Merge conflicts when generating patch, please resolve conflicts and then press ENTER to continue" 1>&2
50
+    read
51
+  fi
52
+  git rerere # record post state
53
+  # stage any new files
54
+  git add . > /dev/null
55
+  # construct a new patch
56
+  git diff --cached -p --raw --{src,dst}-prefix=a/Godeps/_workspace/src/k8s.io/kubernetes/ > "${patch}"
57
+  # cleanup the current state
58
+  git reset HEAD --hard > /dev/null
59
+  git checkout master > /dev/null
60
+  git branch -d kube_rebaser_branch > /dev/null
61
+else
62
+  echo "++ Generating patch for ${selector} without rebasing ..." 2>&1
63
+  git diff -p --raw --{src,dst}-prefix=a/Godeps/_workspace/src/k8s.io/kubernetes/ "${selector}" > "${patch}"
64
+fi
65
+
66
+popd > /dev/null
67
+
68
+echo "++ Applying patch ..." 2>&1
69
+echo 2>&1
70
+set +e
71
+git apply --reject "${patch}"
72
+if [[ $? -ne 0 ]]; then
73
+  echo "++ Not all patches applied, merge *.req into your files or rerun with REBASE=1"
74
+  exit 1
75
+fi
76
+
77
+set -o errexit
78
+git add .
79
+git commit -m "UPSTREAM: $1: " > /dev/null
80
+git commit --amend
81
+echo 2>&1
82
+echo "++ Done" 2>&1
... ...
@@ -510,6 +510,46 @@ os::build::ldflags() {
510 510
   )
511 511
 }
512 512
 
513
+# os::build::require_clean_tree exits if the current Git tree is not clean.
514
+os::build::require_clean_tree() {
515
+  if ! git diff-index --quiet HEAD -- || test $(git ls-files --exclude-standard --others | wc -l) != 0; then
516
+    echo "You can't have any staged or dirty files in $(pwd) for this command."
517
+    echo "Either commit them or unstage them to continue."
518
+    exit 1
519
+  fi
520
+}
521
+
522
+# os::build::commit_range takes one or two arguments - if the first argument is an
523
+# integer, it is assumed to be a pull request and the local origin/pr/# branch is
524
+# used to determine the common range with the second argument. If the first argument
525
+# is not an integer, it is assumed to be a Git commit range and output directly.
526
+os::build::commit_range() {
527
+  if [[ "$1" =~ ^-?[0-9]+$ ]]; then
528
+    local target
529
+    target="$(git rev-parse origin/pr/$1)"
530
+    if [[ $? -ne 0 ]]; then
531
+      echo "Branch does not exist, or you have not configured origin/pr/* style branches from GitHub" 1>&2
532
+      exit 1
533
+    fi
534
+
535
+    local base
536
+    base="$(git merge-base origin/pr/$1 $2)"
537
+    if [[ $? -ne 0 ]]; then
538
+      echo "Branch has no common commits with $2" 1>&2
539
+      exit 1
540
+    fi
541
+    if [[ "${base}" == "${target}" ]]; then
542
+      echo "Branch has already been merged to upstream master, use explicit range instead" 1>&2
543
+      exit 1
544
+    fi
545
+
546
+    echo "${base}...${target}"
547
+    exit 0
548
+  fi
549
+
550
+  echo "$1"
551
+}
552
+
513 553
 os::build::gen-docs() {
514 554
   local cmd="$1"
515 555
   local dest="$2"