gitolite-rugged 1.2.pre.devel → 1.2.1.pre.devel

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/README.md +6 -10
  4. data/gitolite.gemspec +12 -12
  5. data/lib/gitolite/config/repo.rb +2 -2
  6. data/lib/gitolite/config.rb +5 -1
  7. data/lib/gitolite/gitolite_admin.rb +100 -37
  8. data/lib/gitolite/ssh_key.rb +70 -16
  9. data/lib/gitolite/version.rb +1 -1
  10. data/spec/config_spec.rb +7 -8
  11. data/spec/fixtures/gitolite-admin/.gitted/COMMIT_EDITMSG +1 -0
  12. data/spec/fixtures/gitolite-admin/.gitted/HEAD +1 -0
  13. data/spec/fixtures/gitolite-admin/.gitted/config +8 -0
  14. data/spec/fixtures/gitolite-admin/.gitted/description +1 -0
  15. data/spec/fixtures/gitolite-admin/.gitted/hooks/applypatch-msg.sample +15 -0
  16. data/spec/fixtures/gitolite-admin/.gitted/hooks/commit-msg.sample +24 -0
  17. data/spec/fixtures/gitolite-admin/.gitted/hooks/post-update.sample +8 -0
  18. data/spec/fixtures/gitolite-admin/.gitted/hooks/pre-applypatch.sample +14 -0
  19. data/spec/fixtures/gitolite-admin/.gitted/hooks/pre-commit.sample +49 -0
  20. data/spec/fixtures/gitolite-admin/.gitted/hooks/pre-push.sample +54 -0
  21. data/spec/fixtures/gitolite-admin/.gitted/hooks/pre-rebase.sample +169 -0
  22. data/spec/fixtures/gitolite-admin/.gitted/hooks/prepare-commit-msg.sample +36 -0
  23. data/spec/fixtures/gitolite-admin/.gitted/hooks/update.sample +128 -0
  24. data/spec/fixtures/gitolite-admin/.gitted/index +0 -0
  25. data/spec/fixtures/gitolite-admin/.gitted/info/exclude +6 -0
  26. data/spec/fixtures/gitolite-admin/.gitted/logs/HEAD +19 -0
  27. data/spec/fixtures/gitolite-admin/.gitted/logs/refs/heads/master +19 -0
  28. data/spec/fixtures/gitolite-admin/.gitted/objects/04/6aa40bf1f4fbef8fe915274bd8af30784f4974 +0 -0
  29. data/spec/fixtures/gitolite-admin/.gitted/objects/06/3a0c108a0a431fff7d9ea819e55653c6fda14c +3 -0
  30. data/spec/fixtures/gitolite-admin/.gitted/objects/0a/0493ecd1ef1102cc11211b95d19ef7c4823a23 +0 -0
  31. data/spec/fixtures/gitolite-admin/.gitted/objects/0b/8ae0021fafc32dbecbbcdf82bfe1ec3728432b +3 -0
  32. data/spec/fixtures/gitolite-admin/.gitted/objects/0b/9ea7db8498c31c36567cc7dc528e9a06587ef9 +0 -0
  33. data/spec/fixtures/gitolite-admin/.gitted/objects/13/81680579c7e0626544e28bbca00b0c3b5004e2 +2 -0
  34. data/spec/fixtures/gitolite-admin/.gitted/objects/25/2a0e969ccca06c8258f811d2a6f01d883c2a0c +0 -0
  35. data/spec/fixtures/gitolite-admin/.gitted/objects/39/5dfadc8dd72c4d0ab5d28a3cdd83500a41fb1b +0 -0
  36. data/spec/fixtures/gitolite-admin/.gitted/objects/3b/8c81ac4b6d9276920ec06139d959b9aeb25456 +0 -0
  37. data/spec/fixtures/gitolite-admin/.gitted/objects/41/1a9fa047b7c928939882769d2fac89a1c87dd0 +0 -0
  38. data/spec/fixtures/gitolite-admin/.gitted/objects/42/333c37a7910bff07c7e7a95a3d09b3f9966571 +4 -0
  39. data/spec/fixtures/gitolite-admin/.gitted/objects/43/cb5e7b11750c16f2196bd8548e7b6277b372ca +0 -0
  40. data/spec/fixtures/gitolite-admin/.gitted/objects/5c/f57acca019629fd98a3d9014cd63580a74f4ac +2 -0
  41. data/spec/fixtures/gitolite-admin/.gitted/objects/68/b71afffb0b6781d974af6cb93ef076ded21bb5 +1 -0
  42. data/spec/fixtures/gitolite-admin/.gitted/objects/74/0ef5222fcd51ad7eba4a559396fdf856b20482 +0 -0
  43. data/spec/fixtures/gitolite-admin/.gitted/objects/86/692711b922198563496a69cf30ca772f6a6af3 +0 -0
  44. data/spec/fixtures/gitolite-admin/.gitted/objects/94/f2765eb76820309b11de0018dd2a6bc53ae8f7 +2 -0
  45. data/spec/fixtures/gitolite-admin/.gitted/objects/9c/c84c9d97b8fa8d4cb6c52d6495eca4bff04130 +0 -0
  46. data/spec/fixtures/gitolite-admin/.gitted/objects/9d/248211ad73f2fd188f75988dfd9e66431f2e8a +0 -0
  47. data/spec/fixtures/gitolite-admin/.gitted/objects/9d/ce718e57053022f2e184ba94e2b5131fcbe551 +0 -0
  48. data/spec/fixtures/gitolite-admin/.gitted/objects/ac/b157e4a3d567d42132d608db26143b91c4789c +0 -0
  49. data/spec/fixtures/gitolite-admin/.gitted/objects/ad/91cc1d968ad5fdcb8bd0df04db3523d0b98156 +0 -0
  50. data/spec/fixtures/gitolite-admin/.gitted/objects/b3/178d7dfddbc3df3e03eb271f0cdbe864aa902f +0 -0
  51. data/spec/fixtures/gitolite-admin/.gitted/objects/b6/de0801eb994701c5a55a0793796aebc2440372 +0 -0
  52. data/spec/fixtures/gitolite-admin/.gitted/objects/c9/0707f5301413f121360c9b26784167652a3d2a +2 -0
  53. data/spec/fixtures/gitolite-admin/.gitted/objects/c9/3d2aaacc82cb05a88994d2b44691d07477bde9 +2 -0
  54. data/spec/fixtures/gitolite-admin/.gitted/objects/d9/3bb9a696d405af34d9dcafc2e4611e1d5959dd +2 -0
  55. data/spec/fixtures/gitolite-admin/.gitted/objects/df/cd7e43b90664b02a7765c54d45277f54bcd2ee +0 -0
  56. data/spec/fixtures/gitolite-admin/.gitted/objects/e1/57cf40f5a30aa527d77c10840010c4654b4eab +3 -0
  57. data/spec/fixtures/gitolite-admin/.gitted/objects/e3/c37d85f4800ed4fe4a3f4ca49e3b4a85a88ae1 +2 -0
  58. data/spec/fixtures/gitolite-admin/.gitted/objects/f4/a351cf0debfb5ac18061f7cb4e7ff2e5916719 +0 -0
  59. data/spec/fixtures/gitolite-admin/.gitted/refs/heads/master +1 -0
  60. data/spec/fixtures/gitolite-admin/conf/gitolite.conf +5 -0
  61. data/spec/fixtures/gitolite-admin/keydir/admin.pub +1 -0
  62. data/spec/fixtures/gitolite-admin/keydir/bob.pub +1 -0
  63. data/spec/fixtures/keys/{bob.pub → bob/bob.pub} +0 -0
  64. data/spec/fixtures/keys/bob/bob@example.com.pub +1 -0
  65. data/spec/fixtures/keys/bob/desktop/bob.pub +1 -0
  66. data/spec/fixtures/keys/bob/school/bob.pub +1 -0
  67. data/spec/gitolite_admin_spec.rb +0 -1
  68. data/spec/ssh_key_spec.rb +19 -137
  69. metadata +186 -28
  70. data/spec/fixtures/keys/bob+joe@test.zilla.com@desktop.pub +0 -1
  71. data/spec/fixtures/keys/bob-ins@zilla-site.com@desktop.pub +0 -1
  72. data/spec/fixtures/keys/bob.joe@test.zilla.com@desktop.pub +0 -1
  73. data/spec/fixtures/keys/bob@desktop.pub +0 -1
  74. data/spec/fixtures/keys/bob@foo-bar.pub +0 -1
  75. data/spec/fixtures/keys/bob@zilla.com.pub +0 -1
  76. data/spec/fixtures/keys/bob@zilla.com@desktop.pub +0 -1
  77. data/spec/fixtures/keys/jakub123.pub +0 -1
  78. data/spec/fixtures/keys/jakub123@foo.net.pub +0 -1
  79. data/spec/fixtures/keys/joe-bob@god-zilla.com@desktop.pub +0 -1
  80. data/spec/fixtures/keys/joe@sch.ool.edu.pub +0 -1
  81. data/spec/fixtures/keys/joe@sch.ool.edu@desktop.pub +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de63cb865336e69a0371a06372f7f55fe1846812
4
- data.tar.gz: 2b3334e0163d1665b56cfb9825880804e1accf0e
3
+ metadata.gz: af594539d972d1b2f8d7a30e493e83fabec75f01
4
+ data.tar.gz: 1eb4ec207defe5014819bcaf4c0e66cebb367a10
5
5
  SHA512:
6
- metadata.gz: a562980bc44bbf4708c231f7e54b0c29507a9898d0f516fcdf25c3d68a76e2bec304f6bf026951acf640b3cd7d99b5ec9a602183f9a4c9aa1bb5a54a8e9bdd9a
7
- data.tar.gz: a6cc767c3ce52c671793188f4b6eacb200adbd92c069debdcb3d9c16d16b3af9aa80173eb2002e306fa995060312c814fcd9bb30ce91c0061f80608ed9a8dbc1
6
+ metadata.gz: 129b807992315d1d3dbcfaa2fddc18ac674d5d0f25f77d8a1d1ae3527a70635bdc048471e57559be1980c02db6f78a41540e58d0145c61e83b144fd4f15561f0
7
+ data.tar.gz: 60817e257935d2854fcab2466af48494360888f008dcac676078a65e4ae431133e5f897289a5ab0c4289bf48a1545b121fb6df4c37bec170ce4f48181e067b47
data/.gitignore CHANGED
@@ -7,3 +7,6 @@
7
7
  /coverage
8
8
  /junit
9
9
  /tmp
10
+
11
+ # Gemnasium gem configuration file
12
+ config/gemnasium.yml
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  ## gitolite-rugged
2
+ [![Gem Version](https://badge.fury.io/rb/gitolite-rugged.svg)](http://badge.fury.io/rb/gitolite-rugged)
3
+ [![Build Status](https://travis-ci.org/oliverguenther/gitolite-rugged.svg?branch=devel)](https://travis-ci.org/oliverguenther/gitolite-rugged)
4
+ [![Code Climate](https://codeclimate.com/github/oliverguenther/gitolite-rugged.png)](https://codeclimate.com/github/oliverguenther/gitolite-rugged)
5
+
6
+ ### This gem is a fork from the [jbox-gitolite](https://github.com/jbox-web/gitolite) gem employing [libgit2/rugged](https://github.com/libgit2/rugged).
2
7
 
3
- **This gem is a fork from the [jbox-gitolite](https://raw.github.com/jbox-web/gitolite) gem employing [libgit2/rugged](https://github.com/libgit2/rugged).**
4
8
 
5
9
  This gem is designed to provide a Ruby interface to the [Gitolite](https://github.com/sitaramc/gitolite) Git backend system.
6
10
 
@@ -10,14 +14,6 @@ It provides these functionalities :
10
14
  * Repositories Management
11
15
  * Gitolite Admin Repository Bootstrapping
12
16
 
13
- ## Code status
14
-
15
- * [![Gem Version](https://badge.fury.io/rb/gitolite-rugged.svg)](http://badge.fury.io/rb/gitolite-rugged)
16
- * [![Build Status](https://travis-ci.org/oliverguenther/gitolite-rugged.svg?branch=devel)](https://travis-ci.org/oliverguenther/gitolite-rugged)
17
- * [![Code Climate](https://codeclimate.com/github/oliverguenther/gitolite-rugged.png)](https://codeclimate.com/github/oliverguenther/gitolite-rugged)
18
- * [![Dependency Status](https://gemnasium.com/oliverguenther/gitolite-rugged.svg)](https://gemnasium.com/oliverguenther/gitolite-rugged)
19
-
20
-
21
17
  ## Requirements ##
22
18
  * Ruby 1.9.x or 2.0.x
23
19
  * a working [gitolite](https://github.com/sitaramc/gitolite) installation
@@ -103,6 +99,6 @@ Copyright (c) 2014 Oliver Günther (mail@oliverguenther.de)
103
99
 
104
100
  Based on the jbox-gitolite fork by Nicolas Rodriguez, which itself is based on the original gitolite gem by Stafford Brunk.
105
101
 
106
- Copyright (c) 2013-2014 Nicolas Rodriguez (nrodriguez@jbox-web.com), JBox Web (http://www.jbox-web.com) [![endorse](https://api.coderwall.com/n-rodriguez/endorsecount.png)](https://coderwall.com/n-rodriguez)
102
+ Copyright (c) 2013-2014 Nicolas Rodriguez (nrodriguez@jbox-web.com), JBox Web (http://www.jbox-web.com)
107
103
 
108
104
  Copyright (c) 2011-2013 Stafford Brunk (stafford.brunk@gmail.com)
data/gitolite.gemspec CHANGED
@@ -13,21 +13,21 @@ Gem::Specification.new do |s|
13
13
  s.description = %q{This gem is designed to provide a Ruby interface to the Gitolite Git backend system using libgit2/rugged. This gem aims to provide all management functionality that is available via the gitolite-admin repository (like SSH keys, repository permissions, etc)}
14
14
  s.license = 'MIT'
15
15
 
16
- s.add_development_dependency "rake", "~> 10.3.1"
17
- s.add_development_dependency "rdoc", "~> 4.1.1"
18
- s.add_development_dependency "rspec", "~> 2.14.1"
19
- s.add_development_dependency "guard-rspec", "~> 4.2.8"
20
- s.add_development_dependency "guard-spork", "~> 1.5.1"
21
- s.add_development_dependency "forgery", "~> 0.6.0"
22
- s.add_development_dependency "travis-lint", "~> 1.8.0"
16
+ s.add_development_dependency "rake", "~> 10.3", ">= 10.3.1"
17
+ s.add_development_dependency "rdoc", "~> 4.1", ">= 4.1.1"
18
+ s.add_development_dependency "rspec", "~> 2.14", ">= 2.14.1"
19
+ s.add_development_dependency "guard-rspec", "~> 4.2", ">= 4.2.8"
20
+ s.add_development_dependency "guard-spork", "~> 1.5", ">= 1.5.1"
21
+ s.add_development_dependency "forgery", "~> 0.6", ">= 0.6.0"
22
+ s.add_development_dependency "travis-lint", "~> 1.8", ">= 1.8.0"
23
23
 
24
- s.add_development_dependency "simplecov", "~> 0.8.2"
25
- s.add_development_dependency "simplecov-rcov", "~> 0.2.3"
24
+ s.add_development_dependency "simplecov", "~> 0.8", ">= 0.8.2"
25
+ s.add_development_dependency "simplecov-rcov", "~> 0.2", ">= 0.2.3"
26
26
 
27
- s.add_development_dependency "rspec_junit_formatter", "~> 0.1.6"
27
+ s.add_development_dependency "rspec_junit_formatter", "~> 0.1", ">= 0.1.6"
28
28
 
29
- s.add_dependency "rugged", ">= 0.19.0"
30
- s.add_dependency "gratr19", "~> 0.4.4.1"
29
+ s.add_dependency "rugged", "~> 0.19", ">= 0.19.0"
30
+ s.add_dependency "gratr19", "~> 0.4.4", ">= 0.4.4.1"
31
31
 
32
32
  s.files = `git ls-files`.split("\n")
33
33
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -74,11 +74,11 @@ module Gitolite
74
74
  end
75
75
 
76
76
  @config.each do |k, v|
77
- repo += " config " + k + " = " + v + "\n"
77
+ repo += " config " + k + " = " + v.to_s + "\n"
78
78
  end
79
79
 
80
80
  @options.each do |k, v|
81
- repo += " option " + k + " = " + v + "\n"
81
+ repo += " option " + k + " = " + v.to_s + "\n"
82
82
  end
83
83
 
84
84
  repo
@@ -1,4 +1,5 @@
1
1
  require 'tempfile'
2
+ require 'fileutils'
2
3
 
3
4
  module Gitolite
4
5
 
@@ -73,7 +74,7 @@ module Gitolite
73
74
 
74
75
 
75
76
  def to_file(path=".", filename=@filename)
76
- raise ArgumentError, "Path contains a filename or does not exist" unless File.directory?(path)
77
+ FileUtils.mkdir_p(path) unless File.directory?(path)
77
78
 
78
79
  new_conf = File.join(path, filename)
79
80
  File.open(new_conf, "w") do |f|
@@ -119,6 +120,9 @@ module Gitolite
119
120
  def process_config(config)
120
121
  context = [] #will store our context for permissions or config declarations
121
122
 
123
+ # On first call with a custom *.conf, the config might not yet exist
124
+ return unless File.exists?(config)
125
+
122
126
  #Read each line of our config
123
127
  File.open(config, 'r').each do |l|
124
128
 
@@ -1,25 +1,26 @@
1
+ require 'pathname'
1
2
  module Gitolite
2
3
  class GitoliteAdmin
3
4
 
4
5
  attr_accessor :repo
5
6
 
6
- CONF_DIR = "conf"
7
- KEY_DIR = "keydir"
8
-
9
- CONFIG_FILE = "gitolite.conf"
10
- CONFIG_PATH = File.join(CONF_DIR, "gitolite.conf")
11
-
12
-
13
7
  # Default settings
14
- DEFAULT_SETTINGS = {
8
+ DEFAULTS = {
15
9
  # clone/push url settings
16
- git_user: 'git',
10
+ git_user: 'git',
17
11
  hostname: 'localhost',
18
12
 
19
13
  # Commit settings
20
14
  author_name: 'gitolite-rugged gem',
21
15
  author_email: 'gitolite-rugged@localhost',
22
- commit_msg: 'Commited by the gitolite-rugged gem'
16
+ commit_msg: 'Commited by the gitolite-rugged gem',
17
+
18
+ # Gitolite-Admin settings
19
+ config_dir: "conf",
20
+ key_dir: "keydir",
21
+ key_subdir: "",
22
+ config_file: "gitolite.conf",
23
+ lock_file_path: '.lock'
23
24
  }
24
25
 
25
26
  class << self
@@ -37,8 +38,8 @@ module Gitolite
37
38
  end
38
39
 
39
40
  # Check if config file, key directory exist
40
- [ File.join(dir, CONF_DIR), File.join(dir, KEY_DIR),
41
- File.join(dir, CONFIG_PATH)
41
+ [ File.join(dir, DEFAULTS[:config_dir]), File.join(dir, DEFAULTS[:key_dir]),
42
+ File.join(dir, DEFAULTS[:config_dir], DEFAULTS[:config_file])
42
43
  ].each { |f| return false unless File.exists?(f) }
43
44
 
44
45
  true
@@ -53,14 +54,24 @@ module Gitolite
53
54
  # the gitolite-admin repository
54
55
  #
55
56
  # Settings:
57
+ # [Connection]
56
58
  # :git_user: The git user to SSH to (:git_user@localhost:gitolite-admin.git), defaults to 'git'
57
59
  # :private_key: The key file containing the private SSH key for :git_user
58
60
  # :public_key: The key file containing the public SSH key for :git_user
59
61
  # :host: Hostname for clone url. Defaults to 'localhost'
62
+ #
63
+ # [Gitolite-Admin]
64
+ # :config_dir: Config directory within gitolite repository (defaults to 'conf')
65
+ # :key_dir: Public key directory within gitolite repository (defaults to 'keydir')
66
+ # :config_file: Config file to parse (default: 'gitolite.conf')
67
+ # **use only when you use the 'include' directive of gitolite)**
68
+ # :key_subdir: Where to store gitolite-rugged known keys, defaults to '' (i.e., directly in keydir)
69
+ # :lock_file_path: location of the transaction lockfile, defaults to <gitolite-admin.git>/.lock
70
+ #
60
71
  # The settings hash is forwarded to +GitoliteAdmin.new+ as options.
61
72
  def initialize(path, settings = {})
62
73
  @path = path
63
- @settings = DEFAULT_SETTINGS.merge(settings)
74
+ @settings = DEFAULTS.merge(settings)
64
75
 
65
76
  # Ensure SSH key settings exist
66
77
  @settings.fetch(:public_key)
@@ -71,22 +82,39 @@ module Gitolite
71
82
  username: settings[:git_user], publickey: settings[:public_key],
72
83
  privatekey: settings[:private_key] )
73
84
 
74
- @repo =
85
+ @repo =
75
86
  if self.class.is_gitolite_admin_repo?(path)
76
- Rugged::Repository.new(path)
87
+ Rugged::Repository.new(path, credentials: @credentials)
77
88
  else
78
89
  clone
79
90
  end
80
91
 
81
- @config_file_path = File.join(@path, CONF_DIR, CONFIG_FILE)
82
- @conf_dir_path = File.join(@path, CONF_DIR)
83
- @key_dir_path = File.join(@path, KEY_DIR)
92
+ @config_dir_path = File.join(@path, @settings[:config_dir])
93
+ @config_file_path = File.join(@config_dir_path, @settings[:config_file])
94
+ @key_dir_path = File.join(@path, relative_key_dir)
84
95
 
85
96
  @commit_author = { email: settings[:author_email], name: settings[:author_name] }
86
97
 
87
98
  reload!
88
99
  end
89
100
 
101
+
102
+ #
103
+ # Returns the relative directory to the gitolite config file location.
104
+ # I.e., settings[config_dir]/settings[config_file]
105
+ # Defaults to 'conf/gitolite.conf'
106
+ def relative_config_file
107
+ File.join(@settings[:config_dir], @settings[:config_file])
108
+ end
109
+
110
+ #
111
+ # Returns the relative directory to the public key location.
112
+ # I.e., settings[key_dir]/settings[key_subdir]
113
+ # Defaults to 'keydir/'
114
+ def relative_key_dir
115
+ File.join(@settings[:key_dir], @settings[:key_subdir])
116
+ end
117
+
90
118
  def config
91
119
  @config ||= load_config
92
120
  end
@@ -138,28 +166,25 @@ module Gitolite
138
166
 
139
167
  # Writes all changed aspects out to the file system
140
168
  # will also stage all changes then commit
141
- def save()
169
+ def save(commit_msg = nil)
142
170
 
143
171
  # Add all changes to index (staging area)
144
172
  index = @repo.index
145
173
 
146
174
  #Process config file (if loaded, i.e. may be modified)
147
175
  if @config
148
- new_conf = @config.to_file(@conf_dir_path)
149
-
150
- # Rugged wants relative paths
151
- index.add(CONFIG_PATH)
176
+ new_conf = @config.to_file(path=@config_dir_path)
177
+ index.add(relative_config_file)
152
178
  end
153
179
 
154
180
  #Process ssh keys (if loaded, i.e. may be modified)
155
181
  if @ssh_keys
156
- files = list_keys.map{|f| File.basename f}
157
- keys = @ssh_keys.values.map{|f| f.map {|t| t.filename}}.flatten
182
+ files = list_keys.map{|f| relative_key_path(f) }
183
+ keys = @ssh_keys.values.map{|f| f.map {|t| t.relative_path}}.flatten
158
184
 
159
- to_remove = (files - keys).map { |f| File.join(@key_dir, f) }
160
- to_remove.each do |key|
161
- File.unlink key
162
- index.remove key
185
+ to_remove = (files - keys).each do |key|
186
+ SSHKey.remove(key, @key_dir_path)
187
+ index.remove File.join(relative_key_dir, key)
163
188
  end
164
189
 
165
190
  @ssh_keys.each_value do |key|
@@ -167,7 +192,7 @@ module Gitolite
167
192
  next if key.respond_to?(:dirty?) && !key.dirty?
168
193
  key.each do |k|
169
194
  new_key = k.to_file(@key_dir_path)
170
- index.add new_key
195
+ index.add File.join(relative_key_dir, k.relative_path)
171
196
  end
172
197
  end
173
198
  end
@@ -181,7 +206,7 @@ module Gitolite
181
206
  Rugged::Commit.create(@repo,
182
207
  author: commit_author,
183
208
  committer: commit_author,
184
- message: @settings[:commit_msg],
209
+ message: commit_msg || @settings[:commit_msg],
185
210
  parents: [repo.head.target],
186
211
  tree: commit_tree,
187
212
  update_ref: 'HEAD'
@@ -191,7 +216,7 @@ module Gitolite
191
216
 
192
217
  # Push back to origin
193
218
  def apply
194
- @repo.push 'origin', ['refs/heads/master']
219
+ @repo.push('origin', ['refs/heads/master'], credentials: @credentials)
195
220
  end
196
221
 
197
222
 
@@ -202,6 +227,19 @@ module Gitolite
202
227
  end
203
228
 
204
229
 
230
+ # Lock the gitolite-admin directory and yield.
231
+ # After the block is completed, calls +apply+ only.
232
+ # You have to commit your changes within the transaction block
233
+ def transaction
234
+ get_lock do
235
+ yield
236
+
237
+ # Push all changes
238
+ apply
239
+ end
240
+ end
241
+
242
+
205
243
  # Updates the repo with changes from remote master
206
244
  # Warning: This resets the repo before pulling in the changes.
207
245
  def update(settings = {})
@@ -215,7 +253,7 @@ module Gitolite
215
253
  merge_index = repo.merge_commits(master, origin_master)
216
254
 
217
255
  # Complete the merge by comitting it
218
- merge_commit = Rugged::Commit.create(@repo,
256
+ merge_commit = Rugged::Commit.create(@repo,
219
257
  parents: [ master, origin_master ],
220
258
  tree: merge_index.write_tree(@repo),
221
259
  message: '[gitolite-rugged] Merged `origin/master` into `master`',
@@ -232,8 +270,8 @@ module Gitolite
232
270
 
233
271
 
234
272
  # Clone the gitolite-admin repo
235
- # to the given path.
236
- #
273
+ # to the given path.
274
+ #
237
275
  # The repo is cloned from the url
238
276
  # +(:git_user)@(:hostname)/gitolite-admin.git+
239
277
  #
@@ -241,8 +279,8 @@ module Gitolite
241
279
  # E.g., +git@localhost:2222/gitolite-admin.git+
242
280
  #
243
281
  def clone()
244
- Rugged::Repository.clone_at(admin_url(@settings), File.expand_path(@path), credentials: @creds)
245
- end
282
+ Rugged::Repository.clone_at(admin_url(@settings), File.expand_path(@path), credentials: @credentials)
283
+ end
246
284
 
247
285
 
248
286
  def load_config
@@ -254,6 +292,13 @@ module Gitolite
254
292
  Dir.glob(@key_dir_path + '/**/*.pub')
255
293
  end
256
294
 
295
+ # Returns the relative key path
296
+ # <owner>/<location>/<owner> given an absolute path
297
+ # below the keydir.
298
+ def relative_key_path(key_path)
299
+ Pathname.new(key_path).relative_path_from(Pathname.new(@key_dir_path)).to_s
300
+ end
301
+
257
302
 
258
303
  # Loads all .pub files in the gitolite-admin
259
304
  # keydir directory
@@ -272,5 +317,23 @@ module Gitolite
272
317
 
273
318
  keys
274
319
  end
320
+
321
+ def lock_file_path
322
+ File.expand_path(@settings[:lock_file_path], @path)
323
+ end
324
+
325
+
326
+ # Aquire LOCK_EX on the gitolite-admin.git directory .
327
+ # Use +GitoliteAdmin.transaction+ to modify with flock.
328
+ def get_lock
329
+ File.open(lock_file_path, File::RDWR|File::CREAT, 0644) do |file|
330
+ file.sync = true
331
+ file.flock(File::LOCK_EX)
332
+
333
+ yield
334
+
335
+ file.flock(File::LOCK_UN)
336
+ end
337
+ end
275
338
  end
276
339
  end
@@ -1,13 +1,12 @@
1
+ require 'fileutils'
1
2
  module Gitolite
2
3
 
3
4
  # Models an SSH key within gitolite
4
5
  # provides support for multikeys
5
6
  #
6
7
  # Types of multi keys:
7
- # bob.pub => username: bob
8
- # bob@desktop.pub => username: bob, location: desktop
9
- # bob@email.com.pub => username: bob@email.com
10
- # bob@email.com@desktop.pub => username: bob@email.com, location: desktop
8
+ # username: bob => <keydir>/bob/bob.pub
9
+ # username: bob, location: desktop => <keydir>/bob/desktop/bob.pub
11
10
 
12
11
  class SSHKey
13
12
 
@@ -18,17 +17,17 @@ module Gitolite
18
17
  def from_file(key)
19
18
  raise "#{key} does not exist!" unless File.exists?(key)
20
19
 
21
- # TODO this is old-style locations, use folders instead.
22
- # Get our owner and location
23
- File.basename(key) =~ /^([\+\w\.-]+(?:@(?:[\w-]+\.)+\D{2,4})?)(?:@([\w-]+))?.pub$/i
24
- owner = $1
25
- location = $2 || ""
20
+ # Owner is the basename of the key
21
+ # i.e., <owner>/<location>/<owner>.pub
22
+ owner = File.basename(key, ".pub")
23
+
24
+ # Location is the middle section of the path, if any
25
+ location = self.location_from_path(File.dirname(key), owner)
26
26
 
27
27
  # Use string key constructor
28
28
  self.from_string(File.read(key), owner, location)
29
29
  end
30
30
 
31
-
32
31
  # Construct a SSHKey from a string
33
32
  def from_string(key_string, owner, location = "")
34
33
  if owner.nil?
@@ -51,10 +50,58 @@ module Gitolite
51
50
  self.new(type, blob, email, owner, location)
52
51
  end
53
52
 
53
+ # Parse the key path above the key to be read.
54
+ # As we can omit the location, there are two possible options:
55
+ #
56
+ # 1. Location is empty. Path is <keydir>/<owner>/
57
+ # 2. Location is non-empty. Path is <keydir>/<owner>/<location>
58
+ #
59
+ # We test this by checking the parent of the given path.
60
+ # If it equals owner, a location was set.
61
+ # This allows the daft case of e.g., using <keydir>/bob/bob/bob.pub.
62
+ def location_from_path(path, owner)
63
+ keyroot = File.dirname(path)
64
+ if File.basename(keyroot) == owner
65
+ File.basename(path)
66
+ else
67
+ ''
68
+ end
69
+ end
70
+
71
+ def delete_dir_if_empty(dir)
72
+ if File.directory?(dir) && Dir["#{dir}/*"].empty?
73
+ Dir.rmdir(dir)
74
+ end
75
+ rescue => e
76
+ STDERR.puts("Warning: Couldn't delete empty directory: #{e.message}")
77
+ end
78
+
79
+ # Remove a key given a relative path
80
+ #
81
+ # Unlinks the key file and removes any empty parent directory
82
+ # below key_dir
83
+ def remove(key_file, key_dir_path)
84
+
85
+ abs_key_path = File.join(key_dir_path, key_file)
86
+ key = self.from_file(abs_key_path)
87
+
88
+ # Remove the file itself
89
+ File.unlink(abs_key_path)
90
+
91
+ key_owner_dir = File.join(key_dir_path, key.owner)
92
+
93
+ # Remove the location, if it exists and is empty
94
+ if key.location
95
+ self.delete_dir_if_empty(File.join(key_owner_dir, key.location))
96
+ end
97
+
98
+ # Remove the owner dir, if empty
99
+ self.delete_dir_if_empty(key_owner_dir)
100
+ end
54
101
  end
55
102
 
56
103
 
57
- def initialize(type, blob, email, owner = nil, location = "")
104
+ def initialize(type, blob, email, owner=nil, location = "")
58
105
  @type = type
59
106
  @blob = blob
60
107
  @email = email
@@ -70,7 +117,14 @@ module Gitolite
70
117
 
71
118
 
72
119
  def to_file(path)
73
- key_file = File.join(path, self.filename)
120
+ # Ensure multi-key directory structure
121
+ # <keydir>/<owner>/<location?>/<owner>.pub
122
+ key_dir = File.join(path, @owner, @location)
123
+ key_file = File.join(key_dir, self.filename)
124
+
125
+ # Ensure subdirs exist
126
+ FileUtils.mkdir_p(key_dir) unless File.directory?(key_dir)
127
+
74
128
  File.open(key_file, "w") do |f|
75
129
  f.sync = true
76
130
  f.write(self.to_s)
@@ -78,11 +132,12 @@ module Gitolite
78
132
  key_file
79
133
  end
80
134
 
135
+ def relative_path
136
+ File.join(@owner, @location, self.filename)
137
+ end
81
138
 
82
139
  def filename
83
- file = @owner
84
- file += "@#{@location}" unless @location.empty?
85
- file += ".pub"
140
+ [@owner, '.pub'].join
86
141
  end
87
142
 
88
143
 
@@ -98,6 +153,5 @@ module Gitolite
98
153
  def hash
99
154
  [@owner, @location, @type, @blob, @email].hash
100
155
  end
101
-
102
156
  end
103
157
  end
@@ -1,3 +1,3 @@
1
1
  module Gitolite
2
- VERSION = "1.2-devel"
2
+ VERSION = "1.2.1-devel"
3
3
  end
data/spec/config_spec.rb CHANGED
@@ -4,7 +4,6 @@ describe Gitolite::Config do
4
4
 
5
5
  conf_dir = File.join(File.dirname(__FILE__), 'fixtures', 'configs')
6
6
  output_dir = '/tmp'
7
- # output_dir = File.join(File.dirname(File.dirname(__FILE__)), 'tmp')
8
7
 
9
8
  describe "#new" do
10
9
  it 'should read a simple configuration' do
@@ -348,14 +347,14 @@ describe Gitolite::Config do
348
347
  File.unlink(file)
349
348
  end
350
349
 
351
- it 'should raise an ArgumentError when an invalid path is specified' do
350
+ it 'should create the given directory if it does not exist' do
352
351
  c = Gitolite::Config.init
353
- lambda { c.to_file('/does/not/exist') }.should raise_error(ArgumentError)
354
- end
355
-
356
- it 'should raise an ArgumentError when a filename is specified in the path' do
357
- c = Gitolite::Config.init
358
- lambda{ c.to_file('/home/test.rb') }.should raise_error(ArgumentError)
352
+ Dir.mktmpdir("foo") do |dir|
353
+ target = File.join(dir, "someconfigfile")
354
+ File.exists?(target).should eql(false)
355
+ c.to_file(target)
356
+ File.exists?(target).should eql(true)
357
+ end
359
358
  end
360
359
 
361
360
  it 'should resolve group dependencies such that all groups are defined before they are used' do
@@ -0,0 +1 @@
1
+ Initial repos w/ admin+bob
@@ -0,0 +1 @@
1
+ ref: refs/heads/master
@@ -0,0 +1,8 @@
1
+ [core]
2
+ repositoryformatversion = 0
3
+ filemode = true
4
+ bare = false
5
+ logallrefupdates = true
6
+ ignorecase = true
7
+ precomposeunicode = true
8
+ autocrlf = false
@@ -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 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
+ :