winci-updater 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/History.txt +4 -0
  4. data/README.txt +90 -0
  5. data/Rakefile +7 -0
  6. data/features/development.feature +13 -0
  7. data/features/fixtures/files.git/HEAD +1 -0
  8. data/features/fixtures/files.git/config +7 -0
  9. data/features/fixtures/files.git/description +1 -0
  10. data/features/fixtures/files.git/hooks/applypatch-msg.sample +15 -0
  11. data/features/fixtures/files.git/hooks/commit-msg.sample +24 -0
  12. data/features/fixtures/files.git/hooks/post-commit.sample +8 -0
  13. data/features/fixtures/files.git/hooks/post-receive.sample +15 -0
  14. data/features/fixtures/files.git/hooks/post-update.sample +8 -0
  15. data/features/fixtures/files.git/hooks/pre-applypatch.sample +14 -0
  16. data/features/fixtures/files.git/hooks/pre-commit.sample +46 -0
  17. data/features/fixtures/files.git/hooks/pre-rebase.sample +169 -0
  18. data/features/fixtures/files.git/hooks/prepare-commit-msg.sample +36 -0
  19. data/features/fixtures/files.git/hooks/update.sample +128 -0
  20. data/features/fixtures/files.git/info/exclude +6 -0
  21. data/features/fixtures/files.git/objects/03/6fa7341563be59c8a77d97cb9491fa5cf45ceb +0 -0
  22. data/features/fixtures/files.git/objects/05/0a491267bf39675b8299b4a58bf0969b042074 +0 -0
  23. data/features/fixtures/files.git/objects/05/79c80f1bded5c888e4c5d0db0a620a9d862d43 +1 -0
  24. data/features/fixtures/files.git/objects/07/51c79876ff4eb8815818b9272343e3c7e33dea +0 -0
  25. data/features/fixtures/files.git/objects/0f/c94ca3dd1c6b88de8a3cf14f4dcceed8e09660 +0 -0
  26. data/features/fixtures/files.git/objects/11/90f934e40b4f046fcf85ea78db9fee8093abec +0 -0
  27. data/features/fixtures/files.git/objects/15/4cedd3733da97c11bdb7a117d1fae8b518bf34 +1 -0
  28. data/features/fixtures/files.git/objects/1f/71c1a207e09add411a5cecf69c10f55445b469 +0 -0
  29. data/features/fixtures/files.git/objects/20/b002ac4d646c229034cef829ff18624c977eb5 +0 -0
  30. data/features/fixtures/files.git/objects/21/a215f731df78dbd19f996206d7f767eee1b693 +0 -0
  31. data/features/fixtures/files.git/objects/23/9285087a6b72507556d4d3cc112c5fd31d53e0 +0 -0
  32. data/features/fixtures/files.git/objects/2b/9535c8e56553adb9aebb20ad1912e931716150 +0 -0
  33. data/features/fixtures/files.git/objects/2c/4581b957e00fabb337d4721ac5f2e2926c3789 +0 -0
  34. data/features/fixtures/files.git/objects/2c/a3daa8b8f25df70098f4a70841ab6388efa359 +0 -0
  35. data/features/fixtures/files.git/objects/2e/61d627945bcd38b8f9ddf859a74c2b2d02b7b2 +0 -0
  36. data/features/fixtures/files.git/objects/33/cc6691aba73113aa445e3f84a3366f4e98e3e0 +2 -0
  37. data/features/fixtures/files.git/objects/37/cc011ba9639bd5061d6f7b1a3a5dce82cd1f71 +0 -0
  38. data/features/fixtures/files.git/objects/3b/14857a8e7cb009f90cfcd066043031a282db00 +0 -0
  39. data/features/fixtures/files.git/objects/3b/369d6d123b120b39aa8948454bcc37253b5959 +0 -0
  40. data/features/fixtures/files.git/objects/44/a6ee1a915804490c0ad5dffb5ea23e5aa5b812 +0 -0
  41. data/features/fixtures/files.git/objects/69/1ed3b65603a0d0dabfb66720e7163664be78f5 +0 -0
  42. data/features/fixtures/files.git/objects/6a/9904979668a9990f0cf02351422a7236667d47 +2 -0
  43. data/features/fixtures/files.git/objects/6a/b5d1f20357490f4c88e43933c369ec7c70a5c2 +0 -0
  44. data/features/fixtures/files.git/objects/71/eb640bd5dc79c14a3526aef009579548ec98c8 +0 -0
  45. data/features/fixtures/files.git/objects/72/cb06bbb46845dac41abe5c43850b8776713462 +0 -0
  46. data/features/fixtures/files.git/objects/89/e4b6c7d553678c64ce2ca045e9fc9a4361d690 +0 -0
  47. data/features/fixtures/files.git/objects/8d/e9e3b959ac8c2dffe3b7515be1d4956b8baf49 +0 -0
  48. data/features/fixtures/files.git/objects/92/e2e7031fb99e9167e322894d63fc8e0507c2c4 +2 -0
  49. data/features/fixtures/files.git/objects/94/87e688ef97be0548a786bda7950d037c20bbbb +0 -0
  50. data/features/fixtures/files.git/objects/a9/10b1bd4a24ad1b2d62605c857f84c79013b977 +2 -0
  51. data/features/fixtures/files.git/objects/ac/e379a6acc4ab141c97572504a5b9d93f0ddcb1 +0 -0
  52. data/features/fixtures/files.git/objects/b7/5117ab9cc4c4216d06c018bb020df581c2c30d +0 -0
  53. data/features/fixtures/files.git/objects/c9/ca14ae5fd726fe7513f14d51889e48f5adbc3f +0 -0
  54. data/features/fixtures/files.git/objects/d0/925b51ab3408d6fef51d5a40d39ae093fb6540 +2 -0
  55. data/features/fixtures/files.git/objects/da/da52d59d000dacf2495252a374d4cbc3868789 +0 -0
  56. data/features/fixtures/files.git/objects/df/d10fbf3f8b159f9385988b7deb386604598afc +0 -0
  57. data/features/fixtures/files.git/objects/fd/b794eac9712eab2c12866319af6767b8b9e556 +0 -0
  58. data/features/fixtures/files.git/refs/heads/master +1 -0
  59. data/features/step_definitions/common_steps.rb +183 -0
  60. data/features/step_definitions/jenkins_steps.rb +113 -0
  61. data/features/support/common.rb +37 -0
  62. data/features/support/env.rb +20 -0
  63. data/features/support/matchers.rb +9 -0
  64. data/features/works_with_continuous_delivery.feature +18 -0
  65. data/lib/winci-updater.rb +6 -0
  66. data/lib/winci-updater/const.rb +57 -0
  67. data/lib/winci-updater/core_ext/string.rb +9 -0
  68. data/lib/winci-updater/git.rb +134 -0
  69. data/lib/winci-updater/git_ext/base.rb +30 -0
  70. data/lib/winci-updater/git_ext/git.rb +15 -0
  71. data/lib/winci-updater/git_ext/lib.rb +120 -0
  72. data/lib/winci-updater/gui.rb +47 -0
  73. data/lib/winci-updater/logger.rb +54 -0
  74. data/lib/winci-updater/version.rb +5 -0
  75. data/spec/fixtures/files.git/HEAD +1 -0
  76. data/spec/fixtures/files.git/config +10 -0
  77. data/spec/fixtures/files.git/description +1 -0
  78. data/spec/fixtures/files.git/hooks/applypatch-msg.sample +15 -0
  79. data/spec/fixtures/files.git/hooks/commit-msg.sample +24 -0
  80. data/spec/fixtures/files.git/hooks/post-commit.sample +8 -0
  81. data/spec/fixtures/files.git/hooks/post-receive.sample +15 -0
  82. data/spec/fixtures/files.git/hooks/post-update.sample +8 -0
  83. data/spec/fixtures/files.git/hooks/pre-applypatch.sample +14 -0
  84. data/spec/fixtures/files.git/hooks/pre-commit.sample +46 -0
  85. data/spec/fixtures/files.git/hooks/pre-rebase.sample +169 -0
  86. data/spec/fixtures/files.git/hooks/prepare-commit-msg.sample +36 -0
  87. data/spec/fixtures/files.git/hooks/update.sample +128 -0
  88. data/spec/fixtures/files.git/info/exclude +6 -0
  89. data/spec/fixtures/files.git/objects/0d/6b60095e8ee0e285b63964392a346f1a484c76 +0 -0
  90. data/spec/fixtures/files.git/objects/92/2951e4b5e9b3539344ac83aed95005ddc64c7e +0 -0
  91. data/spec/fixtures/files.git/objects/c3/c88adeec62fc2b3cc3494f1a0a34bfb66f2fbe +2 -0
  92. data/spec/fixtures/files.git/refs/heads/master +1 -0
  93. data/spec/fixtures/files_changed.git/HEAD +1 -0
  94. data/spec/fixtures/files_changed.git/config +10 -0
  95. data/spec/fixtures/files_changed.git/description +1 -0
  96. data/spec/fixtures/files_changed.git/hooks/applypatch-msg.sample +15 -0
  97. data/spec/fixtures/files_changed.git/hooks/commit-msg.sample +24 -0
  98. data/spec/fixtures/files_changed.git/hooks/post-commit.sample +8 -0
  99. data/spec/fixtures/files_changed.git/hooks/post-receive.sample +15 -0
  100. data/spec/fixtures/files_changed.git/hooks/post-update.sample +8 -0
  101. data/spec/fixtures/files_changed.git/hooks/pre-applypatch.sample +14 -0
  102. data/spec/fixtures/files_changed.git/hooks/pre-commit.sample +46 -0
  103. data/spec/fixtures/files_changed.git/hooks/pre-rebase.sample +169 -0
  104. data/spec/fixtures/files_changed.git/hooks/prepare-commit-msg.sample +36 -0
  105. data/spec/fixtures/files_changed.git/hooks/update.sample +128 -0
  106. data/spec/fixtures/files_changed.git/info/exclude +6 -0
  107. data/spec/fixtures/files_changed.git/objects/0d/6b60095e8ee0e285b63964392a346f1a484c76 +0 -0
  108. data/spec/fixtures/files_changed.git/objects/2f/a2b556695fb8a023d191859153686e2cb04545 +0 -0
  109. data/spec/fixtures/files_changed.git/objects/49/9050cfcb971c6c684a5f2a2d6638406d8f0865 +0 -0
  110. data/spec/fixtures/files_changed.git/objects/80/e133724c1eb772ee56359c5e71fd200bfb20cc +0 -0
  111. data/spec/fixtures/files_changed.git/objects/92/2951e4b5e9b3539344ac83aed95005ddc64c7e +0 -0
  112. data/spec/fixtures/files_changed.git/objects/c3/c88adeec62fc2b3cc3494f1a0a34bfb66f2fbe +2 -0
  113. data/spec/fixtures/files_changed.git/refs/heads/master +1 -0
  114. data/spec/fixtures/key +27 -0
  115. data/spec/git_spec.rb +49 -0
  116. data/spec/spec_helper.rb +9 -0
  117. data/tasks/cucumber.rake +23 -0
  118. data/tasks/rspec.rake +9 -0
  119. data/winci-updater.gemspec +28 -0
  120. metadata +280 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in winci-updater.gemspec
4
+ gemspec
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ === 0.0.1 2011-04-25
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/README.txt ADDED
@@ -0,0 +1,90 @@
1
+ winci-updater
2
+ ======
3
+
4
+ [WinCI-updater] File updater capable of downloading files over Git (supports SSH).
5
+
6
+ Install
7
+ =======
8
+
9
+ gem install winci-updater
10
+
11
+ Introduction
12
+ =======
13
+
14
+ WinCI-updater is ingredient of WinCI project.
15
+ The purpose of WinCI project is to simplify implementation of the full continuous deployment pipeline the Agile way with Jenkins/Hudson continuous integration server under Windows.
16
+
17
+ It introduces Agile technologies into provisioning process by keeping it integrated with Continuous Integration Server. To do so it incorporates Git DVCS into the process.
18
+
19
+ WinCI-updater is written in Ruby and uses 'ruby-git' project to automate interaction with Git executable.
20
+
21
+ WinCI-updater is intended to be be used in conjunction with WinCI-server, which is another gem containing functionality necessary
22
+ to setup Jenkins CI and enabling to create installation bundle used in provisioning process.
23
+
24
+
25
+ Why This Project
26
+ =======
27
+
28
+ I needed an automatic update process that would keep changes made by end-users on client and at the same time would keep everything up to date with the Continuous Integration Server,
29
+ even if the updates would come so frequent as a few times a day as in Agile developement. Using standard update process where a whole application is beeing downloaded
30
+ from the server, extracted locally and replaced with the old one, each time a new update appear, seem to be inaproppriate for corporate environments because:
31
+ - application bundle ofen weights more than a few megabytes, but corporate computers have usually limited internet connection and so downloading this bundle a few times a day from the server located outside LAN is not efficient
32
+ - extracted app bundle can weight a few hundred of megabytes and so moving/deleting this whole bunch a few times a day only to get small update, slows down corporate computers and also defragments the disks to slow it even more
33
+
34
+ The solution is to incorporate into provisioning a VCS or DVCS such like Git and this project is realization of this solution.
35
+
36
+
37
+ Usage
38
+ =====
39
+
40
+ First download and run WinCI-server.
41
+ Then take a look at test suite (Cucumber stories and RSpec examples in features and spec directories) for examples of usage.
42
+
43
+
44
+ Developer Instructions
45
+ ======================
46
+
47
+ The dependencies for the gem and for developing the gem are managed by Bundler.
48
+
49
+ gem install bundler
50
+ git clone http://github.com/ksob/winci-updater.git
51
+ bundle install
52
+
53
+ The test suite is run with:
54
+
55
+ bundle exec rake
56
+
57
+
58
+ TODO list
59
+ =========
60
+
61
+ * Integration with Gerrit Jenkins plugin
62
+ * Integration with build-publisher Jenkins plugin
63
+ * Incorporating Grit gem for possible enhancements
64
+
65
+
66
+ License
67
+ =======
68
+
69
+ (The MIT License)
70
+
71
+ Copyright (c) 2011 Kamil Sobieraj, ksob\at\rubyforge.org
72
+
73
+ Permission is hereby granted, free of charge, to any person obtaining
74
+ a copy of this software and associated documentation files (the
75
+ 'Software'), to deal in the Software without restriction, including
76
+ without limitation the rights to use, copy, modify, merge, publish,
77
+ distribute, sublicense, and/or sell copies of the Software, and to
78
+ permit persons to whom the Software is furnished to do so, subject to
79
+ the following conditions:
80
+
81
+ The above copyright notice and this permission notice shall be
82
+ included in all copies or substantial portions of the Software.
83
+
84
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
85
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
86
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
87
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
88
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
89
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
90
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ Dir['tasks/**/*.rake'].each { |f| load f }
5
+
6
+ desc "Run RSpec examples; Run cucumber:ok;"
7
+ task :default => [:spec, :features]
@@ -0,0 +1,13 @@
1
+ Feature: Development processes of winci-updater itself (rake tasks)
2
+
3
+ As a winci-updater maintainer or contributor
4
+ I want rake tasks to maintain and release the gem
5
+ So that I can spend time on the tests and code, and not excessive time on maintenance processes
6
+
7
+ Scenario: Generate RubyGem
8
+ Given this project is active project folder
9
+ When I invoke task "rake build"
10
+ Then file with name matching "pkg/winci-updater-*.gem" is created
11
+ And file with name matching "winci-updater.gemspec" is created
12
+ And the file "winci-updater.gemspec" is a valid gemspec
13
+
@@ -0,0 +1 @@
1
+ ref: refs/heads/master
@@ -0,0 +1,7 @@
1
+ [core]
2
+ repositoryformatversion = 0
3
+ filemode = false
4
+ bare = true
5
+ symlinks = false
6
+ ignorecase = true
7
+ hideDotFiles = dotGitOnly
@@ -0,0 +1 @@
1
+ Unnamed repository; edit this file 'description' to name the repository.
@@ -0,0 +1,15 @@
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to check the commit log message taken by
4
+ # applypatch from an e-mail message.
5
+ #
6
+ # The hook should exit with non-zero status after issuing an
7
+ # appropriate message if it wants to stop the commit. The hook is
8
+ # allowed to edit the commit message file.
9
+ #
10
+ # To enable this hook, rename this file to "applypatch-msg".
11
+
12
+ . git-sh-setup
13
+ test -x "$GIT_DIR/hooks/commit-msg" &&
14
+ exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
15
+ :
@@ -0,0 +1,24 @@
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to check the commit log message.
4
+ # Called by git-commit with one argument, the name of the file
5
+ # that has the commit message. The hook should exit with non-zero
6
+ # status after issuing an appropriate message if it wants to stop the
7
+ # commit. The hook is allowed to edit the commit message file.
8
+ #
9
+ # To enable this hook, rename this file to "commit-msg".
10
+
11
+ # Uncomment the below to add a Signed-off-by line to the message.
12
+ # Doing this in a hook is a bad idea in general, but the prepare-commit-msg
13
+ # hook is more suited to it.
14
+ #
15
+ # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
16
+ # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
17
+
18
+ # This example catches duplicate Signed-off-by lines.
19
+
20
+ test "" = "$(grep '^Signed-off-by: ' "$1" |
21
+ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
22
+ echo >&2 Duplicate Signed-off-by lines.
23
+ exit 1
24
+ }
@@ -0,0 +1,8 @@
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script that is called after a successful
4
+ # commit is made.
5
+ #
6
+ # To enable this hook, rename this file to "post-commit".
7
+
8
+ : Nothing
@@ -0,0 +1,15 @@
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script for the "post-receive" event.
4
+ #
5
+ # The "post-receive" script is run after receive-pack has accepted a pack
6
+ # and the repository has been updated. It is passed arguments in through
7
+ # stdin in the form
8
+ # <oldrev> <newrev> <refname>
9
+ # For example:
10
+ # aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
11
+ #
12
+ # see contrib/hooks/ for a sample, or uncomment the next line and
13
+ # rename the file to "post-receive".
14
+
15
+ #. /usr/share/doc/git-core/contrib/hooks/post-receive-email
@@ -0,0 +1,8 @@
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to prepare a packed repository for use over
4
+ # dumb transports.
5
+ #
6
+ # To enable this hook, rename this file to "post-update".
7
+
8
+ exec git-update-server-info
@@ -0,0 +1,14 @@
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to verify what is about to be committed
4
+ # by applypatch from an e-mail message.
5
+ #
6
+ # The hook should exit with non-zero status after issuing an
7
+ # appropriate message if it wants to stop the commit.
8
+ #
9
+ # To enable this hook, rename this file to "pre-applypatch".
10
+
11
+ . git-sh-setup
12
+ test -x "$GIT_DIR/hooks/pre-commit" &&
13
+ exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
14
+ :
@@ -0,0 +1,46 @@
1
+ #!/bin/sh
2
+ #
3
+ # An example hook script to verify what is about to be committed.
4
+ # Called by git-commit with no arguments. The hook should
5
+ # exit with non-zero status after issuing an appropriate message if
6
+ # it wants to stop the commit.
7
+ #
8
+ # To enable this hook, rename this file to "pre-commit".
9
+
10
+ if git-rev-parse --verify HEAD >/dev/null 2>&1
11
+ then
12
+ against=HEAD
13
+ else
14
+ # Initial commit: diff against an empty tree object
15
+ against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
16
+ fi
17
+
18
+ # If you want to allow non-ascii filenames set this variable to true.
19
+ allownonascii=$(git config hooks.allownonascii)
20
+
21
+ # Cross platform projects tend to avoid non-ascii filenames; prevent
22
+ # them from being added to the repository. We exploit the fact that the
23
+ # printable range starts at the space character and ends with tilde.
24
+ if [ "$allownonascii" != "true" ] &&
25
+ # Note that the use of brackets around a tr range is ok here, (it's
26
+ # even required, for portability to Solaris 10's /usr/bin/tr), since
27
+ # the square bracket bytes happen to fall in the designated range.
28
+ test "$(git diff --cached --name-only --diff-filter=A -z $against |
29
+ LC_ALL=C tr -d '[ -~]\0')"
30
+ then
31
+ echo "Error: Attempt to add a non-ascii file name."
32
+ echo
33
+ echo "This can cause problems if you want to work"
34
+ echo "with people on other platforms."
35
+ echo
36
+ echo "To be portable it is advisable to rename the file ..."
37
+ echo
38
+ echo "If you know what you are doing you can disable this"
39
+ echo "check using:"
40
+ echo
41
+ echo " git config hooks.allownonascii true"
42
+ echo
43
+ exit 1
44
+ fi
45
+
46
+ exec git diff-index --check --cached $against --
@@ -0,0 +1,169 @@
1
+ #!/bin/sh
2
+ #
3
+ # Copyright (c) 2006, 2008 Junio C Hamano
4
+ #
5
+ # The "pre-rebase" hook is run just before "git-rebase" starts doing
6
+ # its job, and can prevent the command from running by exiting with
7
+ # non-zero status.
8
+ #
9
+ # The hook is called with the following parameters:
10
+ #
11
+ # $1 -- the upstream the series was forked from.
12
+ # $2 -- the branch being rebased (or empty when rebasing the current branch).
13
+ #
14
+ # This sample shows how to prevent topic branches that are already
15
+ # merged to 'next' branch from getting rebased, because allowing it
16
+ # would result in rebasing already published history.
17
+
18
+ publish=next
19
+ basebranch="$1"
20
+ if test "$#" = 2
21
+ then
22
+ topic="refs/heads/$2"
23
+ else
24
+ topic=`git symbolic-ref HEAD` ||
25
+ exit 0 ;# we do not interrupt rebasing detached HEAD
26
+ fi
27
+
28
+ case "$topic" in
29
+ refs/heads/??/*)
30
+ ;;
31
+ *)
32
+ exit 0 ;# we do not interrupt others.
33
+ ;;
34
+ esac
35
+
36
+ # Now we are dealing with a topic branch being rebased
37
+ # on top of master. Is it OK to rebase it?
38
+
39
+ # Does the topic really exist?
40
+ git show-ref -q "$topic" || {
41
+ echo >&2 "No such branch $topic"
42
+ exit 1
43
+ }
44
+
45
+ # Is topic fully merged to master?
46
+ not_in_master=`git-rev-list --pretty=oneline ^master "$topic"`
47
+ if test -z "$not_in_master"
48
+ then
49
+ echo >&2 "$topic is fully merged to master; better remove it."
50
+ exit 1 ;# we could allow it, but there is no point.
51
+ fi
52
+
53
+ # Is topic ever merged to next? If so you should not be rebasing it.
54
+ only_next_1=`git-rev-list ^master "^$topic" ${publish} | sort`
55
+ only_next_2=`git-rev-list ^master ${publish} | sort`
56
+ if test "$only_next_1" = "$only_next_2"
57
+ then
58
+ not_in_topic=`git-rev-list "^$topic" master`
59
+ if test -z "$not_in_topic"
60
+ then
61
+ echo >&2 "$topic is already up-to-date with master"
62
+ exit 1 ;# we could allow it, but there is no point.
63
+ else
64
+ exit 0
65
+ fi
66
+ else
67
+ not_in_next=`git-rev-list --pretty=oneline ^${publish} "$topic"`
68
+ perl -e '
69
+ my $topic = $ARGV[0];
70
+ my $msg = "* $topic has commits already merged to public branch:\n";
71
+ my (%not_in_next) = map {
72
+ /^([0-9a-f]+) /;
73
+ ($1 => 1);
74
+ } split(/\n/, $ARGV[1]);
75
+ for my $elem (map {
76
+ /^([0-9a-f]+) (.*)$/;
77
+ [$1 => $2];
78
+ } split(/\n/, $ARGV[2])) {
79
+ if (!exists $not_in_next{$elem->[0]}) {
80
+ if ($msg) {
81
+ print STDERR $msg;
82
+ undef $msg;
83
+ }
84
+ print STDERR " $elem->[1]\n";
85
+ }
86
+ }
87
+ ' "$topic" "$not_in_next" "$not_in_master"
88
+ exit 1
89
+ fi
90
+
91
+ exit 0
92
+
93
+ ################################################################
94
+
95
+ This sample hook safeguards topic branches that have been
96
+ published from being rewound.
97
+
98
+ The workflow assumed here is:
99
+
100
+ * Once a topic branch forks from "master", "master" is never
101
+ merged into it again (either directly or indirectly).
102
+
103
+ * Once a topic branch is fully cooked and merged into "master",
104
+ it is deleted. If you need to build on top of it to correct
105
+ earlier mistakes, a new topic branch is created by forking at
106
+ the tip of the "master". This is not strictly necessary, but
107
+ it makes it easier to keep your history simple.
108
+
109
+ * Whenever you need to test or publish your changes to topic
110
+ branches, merge them into "next" branch.
111
+
112
+ The script, being an example, hardcodes the publish branch name
113
+ to be "next", but it is trivial to make it configurable via
114
+ $GIT_DIR/config mechanism.
115
+
116
+ With this workflow, you would want to know:
117
+
118
+ (1) ... if a topic branch has ever been merged to "next". Young
119
+ topic branches can have stupid mistakes you would rather
120
+ clean up before publishing, and things that have not been
121
+ merged into other branches can be easily rebased without
122
+ affecting other people. But once it is published, you would
123
+ not want to rewind it.
124
+
125
+ (2) ... if a topic branch has been fully merged to "master".
126
+ Then you can delete it. More importantly, you should not
127
+ build on top of it -- other people may already want to
128
+ change things related to the topic as patches against your
129
+ "master", so if you need further changes, it is better to
130
+ fork the topic (perhaps with the same name) afresh from the
131
+ tip of "master".
132
+
133
+ Let's look at this example:
134
+
135
+ o---o---o---o---o---o---o---o---o---o "next"
136
+ / / / /
137
+ / a---a---b A / /
138
+ / / / /
139
+ / / c---c---c---c B /
140
+ / / / \ /
141
+ / / / b---b C \ /
142
+ / / / / \ /
143
+ ---o---o---o---o---o---o---o---o---o---o---o "master"
144
+
145
+
146
+ A, B and C are topic branches.
147
+
148
+ * A has one fix since it was merged up to "next".
149
+
150
+ * B has finished. It has been fully merged up to "master" and "next",
151
+ and is ready to be deleted.
152
+
153
+ * C has not merged to "next" at all.
154
+
155
+ We would want to allow C to be rebased, refuse A, and encourage
156
+ B to be deleted.
157
+
158
+ To compute (1):
159
+
160
+ git-rev-list ^master ^topic next
161
+ git-rev-list ^master next
162
+
163
+ if these match, topic has not merged in next at all.
164
+
165
+ To compute (2):
166
+
167
+ git-rev-list master..topic
168
+
169
+ if this is empty, it is fully merged to "master".