SvnLog 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/svnlog +3 -0
- data/lib/svnlog.rb +221 -0
- data/lib/svnlog/index.rb +111 -0
- data/lib/svnlog/log.rb +37 -0
- data/test/data/repos/README.txt +5 -0
- data/test/data/repos/conf/authz +21 -0
- data/test/data/repos/conf/passwd +8 -0
- data/test/data/repos/conf/svnserve.conf +30 -0
- data/test/data/repos/db/current +1 -0
- data/test/data/repos/db/format +1 -0
- data/test/data/repos/db/fs-type +1 -0
- data/test/data/repos/db/revprops/0 +5 -0
- data/test/data/repos/db/revprops/1 +13 -0
- data/test/data/repos/db/revprops/2 +13 -0
- data/test/data/repos/db/revprops/3 +13 -0
- data/test/data/repos/db/revs/0 +11 -0
- data/test/data/repos/db/revs/1 +0 -0
- data/test/data/repos/db/revs/2 +0 -0
- data/test/data/repos/db/revs/3 +0 -0
- data/test/data/repos/db/uuid +1 -0
- data/test/data/repos/db/write-lock +0 -0
- data/test/data/repos/format +1 -0
- data/test/data/repos/hooks/post-commit.tmpl +51 -0
- data/test/data/repos/hooks/post-lock.tmpl +44 -0
- data/test/data/repos/hooks/post-revprop-change.tmpl +56 -0
- data/test/data/repos/hooks/post-unlock.tmpl +42 -0
- data/test/data/repos/hooks/pre-commit.tmpl +70 -0
- data/test/data/repos/hooks/pre-lock.tmpl +64 -0
- data/test/data/repos/hooks/pre-revprop-change.tmpl +66 -0
- data/test/data/repos/hooks/pre-unlock.tmpl +60 -0
- data/test/data/repos/hooks/start-commit.tmpl +54 -0
- data/test/data/repos/locks/db-logs.lock +3 -0
- data/test/data/repos/locks/db.lock +3 -0
- data/test/helper.rb +9 -0
- data/test/test_all.rb +4 -0
- data/test/test_index.rb +71 -0
- data/test/test_log.rb +29 -0
- metadata +96 -0
data/bin/svnlog
ADDED
data/lib/svnlog.rb
ADDED
@@ -0,0 +1,221 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'svnlog/log'
|
4
|
+
require 'svnlog/index'
|
5
|
+
|
6
|
+
require 'optparse'
|
7
|
+
require 'time'
|
8
|
+
|
9
|
+
module Svn
|
10
|
+
module Log
|
11
|
+
|
12
|
+
# The main program
|
13
|
+
class Application
|
14
|
+
|
15
|
+
def initialize(argv = ARGV)
|
16
|
+
@argv = argv
|
17
|
+
end
|
18
|
+
|
19
|
+
# Run the program
|
20
|
+
def run
|
21
|
+
begin
|
22
|
+
create_command(@argv).run
|
23
|
+
rescue
|
24
|
+
puts $!
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates the command
|
29
|
+
def create_command(argv)
|
30
|
+
command = nil
|
31
|
+
name = argv[0]
|
32
|
+
if name
|
33
|
+
command = Application.commands[name.downcase]
|
34
|
+
end
|
35
|
+
command ||= HelpCommand
|
36
|
+
command.new(argv)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns a list of the available commands
|
40
|
+
def self.commands
|
41
|
+
commands = {}
|
42
|
+
Application.constants.each do |c|
|
43
|
+
if c =~ /(.+)Command/
|
44
|
+
commands[$1.downcase] = eval(c)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
commands
|
48
|
+
end
|
49
|
+
|
50
|
+
# A command for displaying command usage
|
51
|
+
class HelpCommand
|
52
|
+
|
53
|
+
def initialize(argv)
|
54
|
+
end
|
55
|
+
|
56
|
+
def run
|
57
|
+
puts "Usage: svnlog <command> [options]"
|
58
|
+
puts
|
59
|
+
puts "Available commands are:"
|
60
|
+
for name in Application.commands.keys.sort
|
61
|
+
puts " #{name}"
|
62
|
+
end
|
63
|
+
puts
|
64
|
+
puts "Type \"svnlog <command> --help\" for help on a specific command."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# A command for populating an index
|
69
|
+
class IndexCommand
|
70
|
+
|
71
|
+
def initialize(argv)
|
72
|
+
parse_options(argv)
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_options(argv)
|
76
|
+
OptionParser.new do |opt|
|
77
|
+
opt.banner = <<END
|
78
|
+
Populates an index with log entries from an SVN repository.
|
79
|
+
|
80
|
+
Examples:
|
81
|
+
svnlog index -p C:\\MyIndex -r svn://server/repos/path/to/something
|
82
|
+
svnlog index -p C:\\MyIndex
|
83
|
+
|
84
|
+
Usage: svnlog index [options]
|
85
|
+
END
|
86
|
+
opt.on("-p", "--path <val>", "The path to the index") { |@path| }
|
87
|
+
opt.on("-r", "--repository-url <val>", "The url of the SVN repository") { |@repository_url| }
|
88
|
+
opt.parse!(argv)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def run
|
93
|
+
Index.new(@path, @repository_url).update
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# A command for displaying information about an index
|
98
|
+
class InfoCommand
|
99
|
+
|
100
|
+
def initialize(argv)
|
101
|
+
parse_options(argv)
|
102
|
+
end
|
103
|
+
|
104
|
+
def parse_options(argv)
|
105
|
+
OptionParser.new do |opt|
|
106
|
+
opt.banner = <<END
|
107
|
+
Displays information about an index.
|
108
|
+
|
109
|
+
Example:
|
110
|
+
svnlog info -p C:\\MyIndex
|
111
|
+
|
112
|
+
Usage: svnlog info [options]
|
113
|
+
END
|
114
|
+
opt.on("-p", "--path <val>", "The path to the index") { |@path| }
|
115
|
+
opt.parse!(argv)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def run
|
120
|
+
index = Index.new(@path)
|
121
|
+
return if index.size == 0
|
122
|
+
puts "Repository URL: #{index.repository_url}"
|
123
|
+
puts "Last Revision: #{index.last_revision}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# A command for searching an index
|
128
|
+
class SearchCommand
|
129
|
+
|
130
|
+
def initialize(argv)
|
131
|
+
parse_options(argv)
|
132
|
+
@printer ||= SvnLogTextPrinter
|
133
|
+
end
|
134
|
+
|
135
|
+
def parse_options(argv)
|
136
|
+
OptionParser.new do |opt|
|
137
|
+
opt.banner = <<END
|
138
|
+
Searches an index for log entries that match a query.
|
139
|
+
|
140
|
+
Examples:
|
141
|
+
svnlog search -p C:\\MyIndex -q \"Fixed\"
|
142
|
+
svnlog search -p C:\\MyIndex -q \"Fixed\" --xml
|
143
|
+
|
144
|
+
Usage: svnlog search [options]
|
145
|
+
END
|
146
|
+
opt.on("-p", "--path <val>", "The path to the index") { |@path| }
|
147
|
+
opt.on("-q", "--query <val>", "The search query") { |@query| }
|
148
|
+
opt.on("-x", "--xml", "Output in XML") { @printer = SvnLogXmlPrinter }
|
149
|
+
opt.parse!(argv)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def run
|
154
|
+
entries = Index.new(@path).search(@query)
|
155
|
+
@printer.print entries
|
156
|
+
end
|
157
|
+
|
158
|
+
# Prints entries in the 'svn log' text format
|
159
|
+
class SvnLogTextPrinter
|
160
|
+
|
161
|
+
def self.print(entries)
|
162
|
+
print_entry_separator
|
163
|
+
for entry in entries
|
164
|
+
print_entry(entry)
|
165
|
+
print_entry_separator
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
def self.print_entry(entry)
|
172
|
+
puts "r#{entry[:revision]} | #{entry[:author]} | #{date(entry)} | #{line_count(entry)}"
|
173
|
+
puts
|
174
|
+
puts entry[:message]
|
175
|
+
end
|
176
|
+
|
177
|
+
def self.print_entry_separator
|
178
|
+
puts "-" * 72
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.date(entry)
|
182
|
+
time = Time.parse(entry[:date]).localtime
|
183
|
+
time.strftime("%Y-%m-%d %H:%M:%S #{DateTime.parse(time.rfc822).zone} (%a, %d %B %Y)")
|
184
|
+
end
|
185
|
+
|
186
|
+
def self.line_count(entry)
|
187
|
+
line_count = entry[:message].count("\n") + 1
|
188
|
+
str = "#{line_count} line"
|
189
|
+
str += "s" if line_count > 1
|
190
|
+
str
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Prints entries in the 'svn log' xml format
|
195
|
+
class SvnLogXmlPrinter
|
196
|
+
|
197
|
+
def self.print(entries)
|
198
|
+
return unless entries.size > 0
|
199
|
+
puts "<?xml version=\"1.0\"?>"
|
200
|
+
puts "<log>"
|
201
|
+
for entry in entries
|
202
|
+
puts "<logentry revision=\"#{entry[:revision]}\">"
|
203
|
+
puts "<author>#{entry[:author]}</author>"
|
204
|
+
puts "<date>#{entry[:date]}</date>"
|
205
|
+
puts "<msg>#{entry[:message]}</msg>"
|
206
|
+
puts "</logentry>"
|
207
|
+
end
|
208
|
+
puts "</log>"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
if __FILE__ == $0 then
|
218
|
+
Svn::Log::Application.new.run
|
219
|
+
end
|
220
|
+
|
221
|
+
|
data/lib/svnlog/index.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'ferret'
|
2
|
+
include Ferret
|
3
|
+
include Ferret::Document
|
4
|
+
include Ferret::Search
|
5
|
+
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
module Svn
|
9
|
+
module Log
|
10
|
+
|
11
|
+
# An index of svn log entries
|
12
|
+
class Index
|
13
|
+
|
14
|
+
def initialize(path = nil, repository_url = nil)
|
15
|
+
@path = path
|
16
|
+
@index = Ferret::Index::Index.new(:path => @path, :key => :revision)
|
17
|
+
# load the properties
|
18
|
+
properties_path = @path && File.join(@path, "properties.yml")
|
19
|
+
@props = Properties.new(properties_path)
|
20
|
+
@props[:repository_url] ||= repository_url
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the path to the index
|
24
|
+
def path
|
25
|
+
@path
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the url of the repository that is indexed
|
29
|
+
def repository_url
|
30
|
+
@props[:repository_url]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the revision number of the last entry indexed
|
34
|
+
def last_revision
|
35
|
+
@props[:last_revision]
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the number of entries in the index
|
39
|
+
def size
|
40
|
+
@index.size
|
41
|
+
end
|
42
|
+
|
43
|
+
# Updates the index with the latest entries
|
44
|
+
def update
|
45
|
+
revision = "#{last_revision.to_i}:HEAD"
|
46
|
+
entries = Log.new(repository_url).find(revision)
|
47
|
+
return if entries.size == 0
|
48
|
+
for entry in entries
|
49
|
+
add_entry(entry)
|
50
|
+
end
|
51
|
+
@index.flush
|
52
|
+
@props[:last_revision] = entries.last[:revision]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns all entries that match the query
|
56
|
+
def search(query)
|
57
|
+
entries = []
|
58
|
+
options = {:num_docs => @index.size, :sort => SortField::FIELD_DOC }
|
59
|
+
for doc_id, score in @index.search(query, options)
|
60
|
+
entries << @index[doc_id]
|
61
|
+
end
|
62
|
+
entries
|
63
|
+
end
|
64
|
+
|
65
|
+
# Close the index when you're done with it
|
66
|
+
def close
|
67
|
+
@index.close
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# Adds a new entry to the index
|
73
|
+
def add_entry(entry)
|
74
|
+
doc = Document.new
|
75
|
+
doc << Field.new(:revision, entry[:revision], Field::Store::YES, Field::Index::UNTOKENIZED)
|
76
|
+
doc << Field.new(:author, entry[:author], Field::Store::YES, Field::Index::UNTOKENIZED)
|
77
|
+
doc << Field.new(:message, entry[:message], Field::Store::YES, Field::Index::TOKENIZED)
|
78
|
+
doc << Field.new(:date, entry[:date], Field::Store::YES, Field::Index::UNTOKENIZED)
|
79
|
+
@index << doc
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# A set of persistent properties
|
84
|
+
class Properties
|
85
|
+
|
86
|
+
def initialize(path = nil)
|
87
|
+
@data = {}
|
88
|
+
@path = path
|
89
|
+
if @path && File.exists?(@path)
|
90
|
+
File.open(@path) do |file|
|
91
|
+
@data = YAML.load(file)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def [](name)
|
97
|
+
@data[name]
|
98
|
+
end
|
99
|
+
|
100
|
+
def []=(name, value)
|
101
|
+
@data[name] = value
|
102
|
+
if @path
|
103
|
+
File.open(@path, "w") do |file|
|
104
|
+
YAML.dump(@data, file)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
data/lib/svnlog/log.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module Svn
|
4
|
+
module Log
|
5
|
+
|
6
|
+
# An svn log
|
7
|
+
class Log
|
8
|
+
|
9
|
+
def initialize(repository_url)
|
10
|
+
@repository_url = repository_url
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns all entries
|
14
|
+
def entries
|
15
|
+
find("1:HEAD")
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns entries that match the specified revision (which can be a range)
|
19
|
+
def find(revision)
|
20
|
+
entries = []
|
21
|
+
doc = REXML::Document.new(`svn log \"#{@repository_url}\" --revision #{revision} --xml`)
|
22
|
+
doc.elements.each('/log/logentry') do |element|
|
23
|
+
entry = {}
|
24
|
+
entry[:revision] = element.attribute('revision').value
|
25
|
+
entry[:author] = element.text('author')
|
26
|
+
entry[:message] = element.text('msg')
|
27
|
+
entry[:date] = element.text('date')
|
28
|
+
entries << entry
|
29
|
+
end
|
30
|
+
entries
|
31
|
+
end
|
32
|
+
|
33
|
+
alias [] find
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
### This file is an example authorization file for svnserve.
|
2
|
+
### Its format is identical to that of mod_authz_svn authorization
|
3
|
+
### files.
|
4
|
+
### As shown below each section defines authorizations for the path and
|
5
|
+
### (optional) repository specified by the section name.
|
6
|
+
### The authorizations follow. An authorization line can refer to a
|
7
|
+
### single user, to a group of users defined in a special [groups]
|
8
|
+
### section, or to anyone using the '*' wildcard. Each definition can
|
9
|
+
### grant read ('r') access, read-write ('rw') access, or no access
|
10
|
+
### ('').
|
11
|
+
|
12
|
+
# [groups]
|
13
|
+
# harry_and_sally = harry,sally
|
14
|
+
|
15
|
+
# [/foo/bar]
|
16
|
+
# harry = rw
|
17
|
+
# * =
|
18
|
+
|
19
|
+
# [repository:/baz/fuz]
|
20
|
+
# @harry_and_sally = rw
|
21
|
+
# * = r
|
@@ -0,0 +1,8 @@
|
|
1
|
+
### This file is an example password file for svnserve.
|
2
|
+
### Its format is similar to that of svnserve.conf. As shown in the
|
3
|
+
### example below it contains one section labelled [users].
|
4
|
+
### The name and password for each user follow, one account per line.
|
5
|
+
|
6
|
+
# [users]
|
7
|
+
# harry = harryssecret
|
8
|
+
# sally = sallyssecret
|
@@ -0,0 +1,30 @@
|
|
1
|
+
### This file controls the configuration of the svnserve daemon, if you
|
2
|
+
### use it to allow access to this repository. (If you only allow
|
3
|
+
### access through http: and/or file: URLs, then this file is
|
4
|
+
### irrelevant.)
|
5
|
+
|
6
|
+
### Visit http://subversion.tigris.org/ for more information.
|
7
|
+
|
8
|
+
# [general]
|
9
|
+
### These options control access to the repository for unauthenticated
|
10
|
+
### and authenticated users. Valid values are "write", "read",
|
11
|
+
### and "none". The sample settings below are the defaults.
|
12
|
+
# anon-access = read
|
13
|
+
# auth-access = write
|
14
|
+
### The password-db option controls the location of the password
|
15
|
+
### database file. Unless you specify a path starting with a /,
|
16
|
+
### the file's location is relative to the conf directory.
|
17
|
+
### Uncomment the line below to use the default password file.
|
18
|
+
# password-db = passwd
|
19
|
+
### The authz-db option controls the location of the authorization
|
20
|
+
### rules for path-based access control. Unless you specify a path
|
21
|
+
### starting with a /, the file's location is relative to the conf
|
22
|
+
### directory. If you don't specify an authz-db, no path-based access
|
23
|
+
### control is done.
|
24
|
+
### Uncomment the line below to use the default authorization file.
|
25
|
+
# authz-db = authz
|
26
|
+
### This option specifies the authentication realm of the repository.
|
27
|
+
### If two repositories have the same authentication realm, they should
|
28
|
+
### have the same password database, and vice versa. The default realm
|
29
|
+
### is repository's uuid.
|
30
|
+
# realm = My First Repository
|
@@ -0,0 +1 @@
|
|
1
|
+
3 2 1
|
@@ -0,0 +1 @@
|
|
1
|
+
1
|
@@ -0,0 +1 @@
|
|
1
|
+
fsfs
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
27638544-d82e-7546-8798-448353dc9678
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
3
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# POST-COMMIT HOOK
|
4
|
+
#
|
5
|
+
# The post-commit hook is invoked after a commit. Subversion runs
|
6
|
+
# this hook by invoking a program (script, executable, binary, etc.)
|
7
|
+
# named 'post-commit' (for which this file is a template) with the
|
8
|
+
# following ordered arguments:
|
9
|
+
#
|
10
|
+
# [1] REPOS-PATH (the path to this repository)
|
11
|
+
# [2] REV (the number of the revision just committed)
|
12
|
+
#
|
13
|
+
# The default working directory for the invocation is undefined, so
|
14
|
+
# the program should set one explicitly if it cares.
|
15
|
+
#
|
16
|
+
# Because the commit has already completed and cannot be undone,
|
17
|
+
# the exit code of the hook program is ignored. The hook program
|
18
|
+
# can use the 'svnlook' utility to help it examine the
|
19
|
+
# newly-committed tree.
|
20
|
+
#
|
21
|
+
# On a Unix system, the normal procedure is to have 'post-commit'
|
22
|
+
# invoke other programs to do the real work, though it may do the
|
23
|
+
# work itself too.
|
24
|
+
#
|
25
|
+
# Note that 'post-commit' must be executable by the user(s) who will
|
26
|
+
# invoke it (typically the user httpd runs as), and that user must
|
27
|
+
# have filesystem-level permission to access the repository.
|
28
|
+
#
|
29
|
+
# On a Windows system, you should name the hook program
|
30
|
+
# 'post-commit.bat' or 'post-commit.exe',
|
31
|
+
# but the basic idea is the same.
|
32
|
+
#
|
33
|
+
# The hook program typically does not inherit the environment of
|
34
|
+
# its parent process. For example, a common problem is for the
|
35
|
+
# PATH environment variable to not be set to its usual value, so
|
36
|
+
# that subprograms fail to launch unless invoked via absolute path.
|
37
|
+
# If you're having unexpected problems with a hook program, the
|
38
|
+
# culprit may be unusual (or missing) environment variables.
|
39
|
+
#
|
40
|
+
# Here is an example hook script, for a Unix /bin/sh interpreter.
|
41
|
+
# For more examples and pre-written hooks, see those in
|
42
|
+
# the Subversion repository at
|
43
|
+
# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
|
44
|
+
# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
|
45
|
+
|
46
|
+
|
47
|
+
REPOS="$1"
|
48
|
+
REV="$2"
|
49
|
+
|
50
|
+
commit-email.pl "$REPOS" "$REV" commit-watchers@example.org
|
51
|
+
log-commit.py --repository "$REPOS" --revision "$REV"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# POST-LOCK HOOK
|
4
|
+
#
|
5
|
+
# The post-lock hook is run after a path is locked. Subversion runs
|
6
|
+
# this hook by invoking a program (script, executable, binary, etc.)
|
7
|
+
# named 'post-lock' (for which this file is a template) with the
|
8
|
+
# following ordered arguments:
|
9
|
+
#
|
10
|
+
# [1] REPOS-PATH (the path to this repository)
|
11
|
+
# [2] USER (the user who created the lock)
|
12
|
+
#
|
13
|
+
# The paths that were just locked are passed to the hook via STDIN (as
|
14
|
+
# of Subversion 1.2, only one path is passed per invocation, but the
|
15
|
+
# plan is to pass all locked paths at once, so the hook program
|
16
|
+
# should be written accordingly).
|
17
|
+
#
|
18
|
+
# The default working directory for the invocation is undefined, so
|
19
|
+
# the program should set one explicitly if it cares.
|
20
|
+
#
|
21
|
+
# Because the lock has already been created and cannot be undone,
|
22
|
+
# the exit code of the hook program is ignored. The hook program
|
23
|
+
# can use the 'svnlook' utility to help it examine the
|
24
|
+
# newly-created lock.
|
25
|
+
#
|
26
|
+
# On a Unix system, the normal procedure is to have 'post-lock'
|
27
|
+
# invoke other programs to do the real work, though it may do the
|
28
|
+
# work itself too.
|
29
|
+
#
|
30
|
+
# Note that 'post-lock' must be executable by the user(s) who will
|
31
|
+
# invoke it (typically the user httpd runs as), and that user must
|
32
|
+
# have filesystem-level permission to access the repository.
|
33
|
+
#
|
34
|
+
# On a Windows system, you should name the hook program
|
35
|
+
# 'post-lock.bat' or 'post-lock.exe',
|
36
|
+
# but the basic idea is the same.
|
37
|
+
#
|
38
|
+
# Here is an example hook script, for a Unix /bin/sh interpreter:
|
39
|
+
|
40
|
+
REPOS="$1"
|
41
|
+
USER="$2"
|
42
|
+
|
43
|
+
# Send email to interested parties, let them know a lock was created:
|
44
|
+
mailer.py lock "$REPOS" "$USER" /path/to/mailer.conf
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# POST-REVPROP-CHANGE HOOK
|
4
|
+
#
|
5
|
+
# The post-revprop-change hook is invoked after a revision property
|
6
|
+
# has been added, modified or deleted. Subversion runs this hook by
|
7
|
+
# invoking a program (script, executable, binary, etc.) named
|
8
|
+
# 'post-revprop-change' (for which this file is a template), with the
|
9
|
+
# following ordered arguments:
|
10
|
+
#
|
11
|
+
# [1] REPOS-PATH (the path to this repository)
|
12
|
+
# [2] REV (the revision that was tweaked)
|
13
|
+
# [3] USER (the username of the person tweaking the property)
|
14
|
+
# [4] PROPNAME (the property that was changed)
|
15
|
+
# [5] ACTION (the property was 'A'dded, 'M'odified, or 'D'eleted)
|
16
|
+
#
|
17
|
+
# [STDIN] PROPVAL ** the old property value is passed via STDIN.
|
18
|
+
#
|
19
|
+
# Because the propchange has already completed and cannot be undone,
|
20
|
+
# the exit code of the hook program is ignored. The hook program
|
21
|
+
# can use the 'svnlook' utility to help it examine the
|
22
|
+
# new property value.
|
23
|
+
#
|
24
|
+
# On a Unix system, the normal procedure is to have 'post-revprop-change'
|
25
|
+
# invoke other programs to do the real work, though it may do the
|
26
|
+
# work itself too.
|
27
|
+
#
|
28
|
+
# Note that 'post-revprop-change' must be executable by the user(s) who will
|
29
|
+
# invoke it (typically the user httpd runs as), and that user must
|
30
|
+
# have filesystem-level permission to access the repository.
|
31
|
+
#
|
32
|
+
# On a Windows system, you should name the hook program
|
33
|
+
# 'post-revprop-change.bat' or 'post-revprop-change.exe',
|
34
|
+
# but the basic idea is the same.
|
35
|
+
#
|
36
|
+
# The hook program typically does not inherit the environment of
|
37
|
+
# its parent process. For example, a common problem is for the
|
38
|
+
# PATH environment variable to not be set to its usual value, so
|
39
|
+
# that subprograms fail to launch unless invoked via absolute path.
|
40
|
+
# If you're having unexpected problems with a hook program, the
|
41
|
+
# culprit may be unusual (or missing) environment variables.
|
42
|
+
#
|
43
|
+
# Here is an example hook script, for a Unix /bin/sh interpreter.
|
44
|
+
# For more examples and pre-written hooks, see those in
|
45
|
+
# the Subversion repository at
|
46
|
+
# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
|
47
|
+
# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
|
48
|
+
|
49
|
+
|
50
|
+
REPOS="$1"
|
51
|
+
REV="$2"
|
52
|
+
USER="$3"
|
53
|
+
PROPNAME="$4"
|
54
|
+
ACTION="$5"
|
55
|
+
|
56
|
+
propchange-email.pl "$REPOS" "$REV" "$USER" "$PROPNAME" watchers@example.org
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# POST-UNLOCK HOOK
|
4
|
+
#
|
5
|
+
# The post-unlock hook runs after a path is unlocked. Subversion runs
|
6
|
+
# this hook by invoking a program (script, executable, binary, etc.)
|
7
|
+
# named 'post-unlock' (for which this file is a template) with the
|
8
|
+
# following ordered arguments:
|
9
|
+
#
|
10
|
+
# [1] REPOS-PATH (the path to this repository)
|
11
|
+
# [2] USER (the user who destroyed the lock)
|
12
|
+
#
|
13
|
+
# The paths that were just unlocked are passed to the hook via STDIN
|
14
|
+
# (as of Subversion 1.2, only one path is passed per invocation, but
|
15
|
+
# the plan is to pass all unlocked paths at once, so the hook program
|
16
|
+
# should be written accordingly).
|
17
|
+
#
|
18
|
+
# The default working directory for the invocation is undefined, so
|
19
|
+
# the program should set one explicitly if it cares.
|
20
|
+
#
|
21
|
+
# Because the lock has already been destroyed and cannot be undone,
|
22
|
+
# the exit code of the hook program is ignored.
|
23
|
+
#
|
24
|
+
# On a Unix system, the normal procedure is to have 'post-unlock'
|
25
|
+
# invoke other programs to do the real work, though it may do the
|
26
|
+
# work itself too.
|
27
|
+
#
|
28
|
+
# Note that 'post-unlock' must be executable by the user(s) who will
|
29
|
+
# invoke it (typically the user httpd runs as), and that user must
|
30
|
+
# have filesystem-level permission to access the repository.
|
31
|
+
#
|
32
|
+
# On a Windows system, you should name the hook program
|
33
|
+
# 'post-unlock.bat' or 'post-unlock.exe',
|
34
|
+
# but the basic idea is the same.
|
35
|
+
#
|
36
|
+
# Here is an example hook script, for a Unix /bin/sh interpreter:
|
37
|
+
|
38
|
+
REPOS="$1"
|
39
|
+
USER="$2"
|
40
|
+
|
41
|
+
# Send email to interested parties, let them know a lock was removed:
|
42
|
+
mailer.py unlock "$REPOS" "$USER" /path/to/mailer.conf
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# PRE-COMMIT HOOK
|
4
|
+
#
|
5
|
+
# The pre-commit hook is invoked before a Subversion txn is
|
6
|
+
# committed. Subversion runs this hook by invoking a program
|
7
|
+
# (script, executable, binary, etc.) named 'pre-commit' (for which
|
8
|
+
# this file is a template), with the following ordered arguments:
|
9
|
+
#
|
10
|
+
# [1] REPOS-PATH (the path to this repository)
|
11
|
+
# [2] TXN-NAME (the name of the txn about to be committed)
|
12
|
+
#
|
13
|
+
# The default working directory for the invocation is undefined, so
|
14
|
+
# the program should set one explicitly if it cares.
|
15
|
+
#
|
16
|
+
# If the hook program exits with success, the txn is committed; but
|
17
|
+
# if it exits with failure (non-zero), the txn is aborted, no commit
|
18
|
+
# takes place, and STDERR is returned to the client. The hook
|
19
|
+
# program can use the 'svnlook' utility to help it examine the txn.
|
20
|
+
#
|
21
|
+
# On a Unix system, the normal procedure is to have 'pre-commit'
|
22
|
+
# invoke other programs to do the real work, though it may do the
|
23
|
+
# work itself too.
|
24
|
+
#
|
25
|
+
# *** NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT ***
|
26
|
+
# *** FOR REVISION PROPERTIES (like svn:log or svn:author). ***
|
27
|
+
#
|
28
|
+
# This is why we recommend using the read-only 'svnlook' utility.
|
29
|
+
# In the future, Subversion may enforce the rule that pre-commit
|
30
|
+
# hooks should not modify the versioned data in txns, or else come
|
31
|
+
# up with a mechanism to make it safe to do so (by informing the
|
32
|
+
# committing client of the changes). However, right now neither
|
33
|
+
# mechanism is implemented, so hook writers just have to be careful.
|
34
|
+
#
|
35
|
+
# Note that 'pre-commit' must be executable by the user(s) who will
|
36
|
+
# invoke it (typically the user httpd runs as), and that user must
|
37
|
+
# have filesystem-level permission to access the repository.
|
38
|
+
#
|
39
|
+
# On a Windows system, you should name the hook program
|
40
|
+
# 'pre-commit.bat' or 'pre-commit.exe',
|
41
|
+
# but the basic idea is the same.
|
42
|
+
#
|
43
|
+
# The hook program typically does not inherit the environment of
|
44
|
+
# its parent process. For example, a common problem is for the
|
45
|
+
# PATH environment variable to not be set to its usual value, so
|
46
|
+
# that subprograms fail to launch unless invoked via absolute path.
|
47
|
+
# If you're having unexpected problems with a hook program, the
|
48
|
+
# culprit may be unusual (or missing) environment variables.
|
49
|
+
#
|
50
|
+
# Here is an example hook script, for a Unix /bin/sh interpreter.
|
51
|
+
# For more examples and pre-written hooks, see those in
|
52
|
+
# the Subversion repository at
|
53
|
+
# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
|
54
|
+
# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
|
55
|
+
|
56
|
+
|
57
|
+
REPOS="$1"
|
58
|
+
TXN="$2"
|
59
|
+
|
60
|
+
# Make sure that the log message contains some text.
|
61
|
+
SVNLOOK=/usr/local/bin/svnlook
|
62
|
+
$SVNLOOK log -t "$TXN" "$REPOS" | \
|
63
|
+
grep "[a-zA-Z0-9]" > /dev/null || exit 1
|
64
|
+
|
65
|
+
# Check that the author of this commit has the rights to perform
|
66
|
+
# the commit on the files and directories being modified.
|
67
|
+
commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1
|
68
|
+
|
69
|
+
# All checks passed, so allow the commit.
|
70
|
+
exit 0
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# PRE-LOCK HOOK
|
4
|
+
#
|
5
|
+
# The pre-lock hook is invoked before an exclusive lock is
|
6
|
+
# created. Subversion runs this hook by invoking a program
|
7
|
+
# (script, executable, binary, etc.) named 'pre-lock' (for which
|
8
|
+
# this file is a template), with the following ordered arguments:
|
9
|
+
#
|
10
|
+
# [1] REPOS-PATH (the path to this repository)
|
11
|
+
# [2] PATH (the path in the repository about to be locked)
|
12
|
+
# [3] USER (the user creating the lock)
|
13
|
+
#
|
14
|
+
# The default working directory for the invocation is undefined, so
|
15
|
+
# the program should set one explicitly if it cares.
|
16
|
+
#
|
17
|
+
# If the hook program exits with success, the lock is created; but
|
18
|
+
# if it exits with failure (non-zero), the lock action is aborted
|
19
|
+
# and STDERR is returned to the client.
|
20
|
+
|
21
|
+
# On a Unix system, the normal procedure is to have 'pre-lock'
|
22
|
+
# invoke other programs to do the real work, though it may do the
|
23
|
+
# work itself too.
|
24
|
+
#
|
25
|
+
# Note that 'pre-lock' must be executable by the user(s) who will
|
26
|
+
# invoke it (typically the user httpd runs as), and that user must
|
27
|
+
# have filesystem-level permission to access the repository.
|
28
|
+
#
|
29
|
+
# On a Windows system, you should name the hook program
|
30
|
+
# 'pre-lock.bat' or 'pre-lock.exe',
|
31
|
+
# but the basic idea is the same.
|
32
|
+
#
|
33
|
+
# Here is an example hook script, for a Unix /bin/sh interpreter:
|
34
|
+
|
35
|
+
REPOS="$1"
|
36
|
+
PATH="$2"
|
37
|
+
USER="$3"
|
38
|
+
|
39
|
+
# If a lock exists and is owned by a different person, don't allow it
|
40
|
+
# to be stolen (e.g., with 'svn lock --force ...').
|
41
|
+
|
42
|
+
# (Maybe this script could send email to the lock owner?)
|
43
|
+
SVNLOOK=/usr/local/bin/svnlook
|
44
|
+
GREP=/bin/grep
|
45
|
+
SED=/bin/sed
|
46
|
+
|
47
|
+
LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \
|
48
|
+
$GREP '^Owner: ' | $SED 's/Owner: //'`
|
49
|
+
|
50
|
+
# If we get no result from svnlook, there's no lock, allow the lock to
|
51
|
+
# happen:
|
52
|
+
if [ "$LOCK_OWNER" == "" ]; then
|
53
|
+
exit 0
|
54
|
+
fi
|
55
|
+
|
56
|
+
# If the person locking matches the lock's owner, allow the lock to
|
57
|
+
# happen:
|
58
|
+
if [ "$LOCK_OWNER" == "$USER" ]; then
|
59
|
+
exit 0
|
60
|
+
fi
|
61
|
+
|
62
|
+
# Otherwise, we've got an owner mismatch, so return failure:
|
63
|
+
echo "Error: $PATH already locked by ${LOCK_OWNER}." 1>&2
|
64
|
+
exit 1
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# PRE-REVPROP-CHANGE HOOK
|
4
|
+
#
|
5
|
+
# The pre-revprop-change hook is invoked before a revision property
|
6
|
+
# is added, modified or deleted. Subversion runs this hook by invoking
|
7
|
+
# a program (script, executable, binary, etc.) named 'pre-revprop-change'
|
8
|
+
# (for which this file is a template), with the following ordered
|
9
|
+
# arguments:
|
10
|
+
#
|
11
|
+
# [1] REPOS-PATH (the path to this repository)
|
12
|
+
# [2] REVISION (the revision being tweaked)
|
13
|
+
# [3] USER (the username of the person tweaking the property)
|
14
|
+
# [4] PROPNAME (the property being set on the revision)
|
15
|
+
# [5] ACTION (the property is being 'A'dded, 'M'odified, or 'D'eleted)
|
16
|
+
#
|
17
|
+
# [STDIN] PROPVAL ** the new property value is passed via STDIN.
|
18
|
+
#
|
19
|
+
# If the hook program exits with success, the propchange happens; but
|
20
|
+
# if it exits with failure (non-zero), the propchange doesn't happen.
|
21
|
+
# The hook program can use the 'svnlook' utility to examine the
|
22
|
+
# existing value of the revision property.
|
23
|
+
#
|
24
|
+
# WARNING: unlike other hooks, this hook MUST exist for revision
|
25
|
+
# properties to be changed. If the hook does not exist, Subversion
|
26
|
+
# will behave as if the hook were present, but failed. The reason
|
27
|
+
# for this is that revision properties are UNVERSIONED, meaning that
|
28
|
+
# a successful propchange is destructive; the old value is gone
|
29
|
+
# forever. We recommend the hook back up the old value somewhere.
|
30
|
+
#
|
31
|
+
# On a Unix system, the normal procedure is to have 'pre-revprop-change'
|
32
|
+
# invoke other programs to do the real work, though it may do the
|
33
|
+
# work itself too.
|
34
|
+
#
|
35
|
+
# Note that 'pre-revprop-change' must be executable by the user(s) who will
|
36
|
+
# invoke it (typically the user httpd runs as), and that user must
|
37
|
+
# have filesystem-level permission to access the repository.
|
38
|
+
#
|
39
|
+
# On a Windows system, you should name the hook program
|
40
|
+
# 'pre-revprop-change.bat' or 'pre-revprop-change.exe',
|
41
|
+
# but the basic idea is the same.
|
42
|
+
#
|
43
|
+
# The hook program typically does not inherit the environment of
|
44
|
+
# its parent process. For example, a common problem is for the
|
45
|
+
# PATH environment variable to not be set to its usual value, so
|
46
|
+
# that subprograms fail to launch unless invoked via absolute path.
|
47
|
+
# If you're having unexpected problems with a hook program, the
|
48
|
+
# culprit may be unusual (or missing) environment variables.
|
49
|
+
#
|
50
|
+
# Here is an example hook script, for a Unix /bin/sh interpreter.
|
51
|
+
# For more examples and pre-written hooks, see those in
|
52
|
+
# the Subversion repository at
|
53
|
+
# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
|
54
|
+
# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
|
55
|
+
|
56
|
+
|
57
|
+
REPOS="$1"
|
58
|
+
REV="$2"
|
59
|
+
USER="$3"
|
60
|
+
PROPNAME="$4"
|
61
|
+
ACTION="$5"
|
62
|
+
|
63
|
+
if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi
|
64
|
+
|
65
|
+
echo "Changing revision properties other than svn:log is prohibited" >&2
|
66
|
+
exit 1
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# PRE-UNLOCK HOOK
|
4
|
+
#
|
5
|
+
# The pre-unlock hook is invoked before an exclusive lock is
|
6
|
+
# destroyed. Subversion runs this hook by invoking a program
|
7
|
+
# (script, executable, binary, etc.) named 'pre-unlock' (for which
|
8
|
+
# this file is a template), with the following ordered arguments:
|
9
|
+
#
|
10
|
+
# [1] REPOS-PATH (the path to this repository)
|
11
|
+
# [2] PATH (the path in the repository about to be unlocked)
|
12
|
+
# [3] USER (the user destroying the lock)
|
13
|
+
#
|
14
|
+
# The default working directory for the invocation is undefined, so
|
15
|
+
# the program should set one explicitly if it cares.
|
16
|
+
#
|
17
|
+
# If the hook program exits with success, the lock is destroyed; but
|
18
|
+
# if it exits with failure (non-zero), the unlock action is aborted
|
19
|
+
# and STDERR is returned to the client.
|
20
|
+
|
21
|
+
# On a Unix system, the normal procedure is to have 'pre-unlock'
|
22
|
+
# invoke other programs to do the real work, though it may do the
|
23
|
+
# work itself too.
|
24
|
+
#
|
25
|
+
# Note that 'pre-unlock' must be executable by the user(s) who will
|
26
|
+
# invoke it (typically the user httpd runs as), and that user must
|
27
|
+
# have filesystem-level permission to access the repository.
|
28
|
+
#
|
29
|
+
# On a Windows system, you should name the hook program
|
30
|
+
# 'pre-unlock.bat' or 'pre-unlock.exe',
|
31
|
+
# but the basic idea is the same.
|
32
|
+
#
|
33
|
+
# Here is an example hook script, for a Unix /bin/sh interpreter:
|
34
|
+
|
35
|
+
REPOS="$1"
|
36
|
+
PATH="$2"
|
37
|
+
USER="$3"
|
38
|
+
|
39
|
+
# If a lock is owned by a different person, don't allow it be broken.
|
40
|
+
# (Maybe this script could send email to the lock owner?)
|
41
|
+
|
42
|
+
SVNLOOK=/usr/local/bin/svnlook
|
43
|
+
GREP=/bin/grep
|
44
|
+
SED=/bin/sed
|
45
|
+
|
46
|
+
LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \
|
47
|
+
$GREP '^Owner: ' | $SED 's/Owner: //'`
|
48
|
+
|
49
|
+
# If we get no result from svnlook, there's no lock, return success:
|
50
|
+
if [ "$LOCK_OWNER" == "" ]; then
|
51
|
+
exit 0
|
52
|
+
fi
|
53
|
+
# If the person unlocking matches the lock's owner, return success:
|
54
|
+
if [ "$LOCK_OWNER" == "$USER" ]; then
|
55
|
+
exit 0
|
56
|
+
fi
|
57
|
+
|
58
|
+
# Otherwise, we've got an owner mismatch, so return failure:
|
59
|
+
echo "Error: $PATH locked by ${LOCK_OWNER}." 1>&2
|
60
|
+
exit 1
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# START-COMMIT HOOK
|
4
|
+
#
|
5
|
+
# The start-commit hook is invoked before a Subversion txn is created
|
6
|
+
# in the process of doing a commit. Subversion runs this hook
|
7
|
+
# by invoking a program (script, executable, binary, etc.) named
|
8
|
+
# 'start-commit' (for which this file is a template)
|
9
|
+
# with the following ordered arguments:
|
10
|
+
#
|
11
|
+
# [1] REPOS-PATH (the path to this repository)
|
12
|
+
# [2] USER (the authenticated user attempting to commit)
|
13
|
+
#
|
14
|
+
# The default working directory for the invocation is undefined, so
|
15
|
+
# the program should set one explicitly if it cares.
|
16
|
+
#
|
17
|
+
# If the hook program exits with success, the commit continues; but
|
18
|
+
# if it exits with failure (non-zero), the commit is stopped before
|
19
|
+
# a Subversion txn is created, and STDERR is returned to the client.
|
20
|
+
#
|
21
|
+
# On a Unix system, the normal procedure is to have 'start-commit'
|
22
|
+
# invoke other programs to do the real work, though it may do the
|
23
|
+
# work itself too.
|
24
|
+
#
|
25
|
+
# Note that 'start-commit' must be executable by the user(s) who will
|
26
|
+
# invoke it (typically the user httpd runs as), and that user must
|
27
|
+
# have filesystem-level permission to access the repository.
|
28
|
+
#
|
29
|
+
# On a Windows system, you should name the hook program
|
30
|
+
# 'start-commit.bat' or 'start-commit.exe',
|
31
|
+
# but the basic idea is the same.
|
32
|
+
#
|
33
|
+
# The hook program typically does not inherit the environment of
|
34
|
+
# its parent process. For example, a common problem is for the
|
35
|
+
# PATH environment variable to not be set to its usual value, so
|
36
|
+
# that subprograms fail to launch unless invoked via absolute path.
|
37
|
+
# If you're having unexpected problems with a hook program, the
|
38
|
+
# culprit may be unusual (or missing) environment variables.
|
39
|
+
#
|
40
|
+
# Here is an example hook script, for a Unix /bin/sh interpreter.
|
41
|
+
# For more examples and pre-written hooks, see those in
|
42
|
+
# the Subversion repository at
|
43
|
+
# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
|
44
|
+
# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
|
45
|
+
|
46
|
+
|
47
|
+
REPOS="$1"
|
48
|
+
USER="$2"
|
49
|
+
|
50
|
+
commit-allower.pl --repository "$REPOS" --user "$USER" || exit 1
|
51
|
+
special-auth-check.py --user "$USER" --auth-level 3 || exit 1
|
52
|
+
|
53
|
+
# All checks passed, so allow the commit.
|
54
|
+
exit 0
|
data/test/helper.rb
ADDED
data/test/test_all.rb
ADDED
data/test/test_index.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
class IndexTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
TEMP_DIR = File.join(Dir.tmpdir, "SvnLogTest")
|
9
|
+
|
10
|
+
# Create the index
|
11
|
+
def setup
|
12
|
+
FileUtils.makedirs(TEMP_DIR)
|
13
|
+
path = File.join(TEMP_DIR, "index")
|
14
|
+
@index = Index.new(path, REPOSITORY_URL)
|
15
|
+
@index.update
|
16
|
+
end
|
17
|
+
|
18
|
+
# Delete the index
|
19
|
+
def teardown
|
20
|
+
@index.close
|
21
|
+
FileUtils.remove_dir(TEMP_DIR, true)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_duplicate_entries_not_added
|
25
|
+
assert_equal 3, @index.size
|
26
|
+
@index.update
|
27
|
+
assert_equal 3, @index.size
|
28
|
+
end
|
29
|
+
|
30
|
+
# The index should remember the url of the repository resource it is indexing
|
31
|
+
def test_remember_repository_url
|
32
|
+
index = Index.new(@index.path)
|
33
|
+
assert_equal REPOSITORY_URL, index.repository_url
|
34
|
+
end
|
35
|
+
|
36
|
+
# The index should remember the revision of the last entry indexed
|
37
|
+
def test_remember_last_revision
|
38
|
+
index = Index.new(@index.path)
|
39
|
+
assert_equal "3", index.last_revision
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_default_search
|
43
|
+
entries = @index.search("Changed")
|
44
|
+
assert_equal 1, entries.size
|
45
|
+
entries.each do |entry|
|
46
|
+
assert_equal "2", entry[:revision]
|
47
|
+
assert_equal "Josh", entry[:author]
|
48
|
+
assert_equal "Changed a few things", entry[:message]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_message_search
|
53
|
+
entries = @index.search("message:Changed")
|
54
|
+
assert_equal 1, entries.size
|
55
|
+
entries.each do |entry|
|
56
|
+
assert_equal "2", entry[:revision]
|
57
|
+
assert_equal "Josh", entry[:author]
|
58
|
+
assert_equal "Changed a few things", entry[:message]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_revision_search
|
63
|
+
entries = @index.search("revision:2")
|
64
|
+
assert_equal 1, entries.size
|
65
|
+
entries.each do |entry|
|
66
|
+
assert_equal "2", entry[:revision]
|
67
|
+
assert_equal "Josh", entry[:author]
|
68
|
+
assert_equal "Changed a few things", entry[:message]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/test/test_log.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class LogTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@log = Log.new(REPOSITORY_URL)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_find_single_entry
|
10
|
+
entries = @log.find("2")
|
11
|
+
assert_equal 1, entries.size
|
12
|
+
entry = entries[0]
|
13
|
+
assert_equal "Josh", entry[:author]
|
14
|
+
assert_equal "Changed a few things", entry[:message]
|
15
|
+
entries = @log["2"]
|
16
|
+
assert_equal 1, entries.size
|
17
|
+
entry = entries[0]
|
18
|
+
assert_equal "Josh", entry[:author]
|
19
|
+
assert_equal "Changed a few things", entry[:message]
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_find_all_entries
|
23
|
+
entries = @log.entries
|
24
|
+
assert_equal 3, entries.size
|
25
|
+
assert_equal "1", entries[0][:revision]
|
26
|
+
assert_equal "2", entries[1][:revision]
|
27
|
+
assert_equal "3", entries[2][:revision]
|
28
|
+
end
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.10
|
3
|
+
specification_version: 1
|
4
|
+
name: SvnLog
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2006-06-13
|
8
|
+
summary: Full-text search of Subversion commit logs
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: jdaltry@gmail.com
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable: svnlog
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
authors:
|
28
|
+
- Josh Daltry
|
29
|
+
files:
|
30
|
+
- bin/svnlog
|
31
|
+
- lib/svnlog
|
32
|
+
- lib/svnlog.rb
|
33
|
+
- lib/svnlog/index.rb
|
34
|
+
- lib/svnlog/log.rb
|
35
|
+
- test/data
|
36
|
+
- test/helper.rb
|
37
|
+
- test/test_all.rb
|
38
|
+
- test/test_index.rb
|
39
|
+
- test/test_log.rb
|
40
|
+
- test/data/repos
|
41
|
+
- test/data/repos/conf
|
42
|
+
- test/data/repos/dav
|
43
|
+
- test/data/repos/db
|
44
|
+
- test/data/repos/format
|
45
|
+
- test/data/repos/hooks
|
46
|
+
- test/data/repos/locks
|
47
|
+
- test/data/repos/README.txt
|
48
|
+
- test/data/repos/conf/authz
|
49
|
+
- test/data/repos/conf/passwd
|
50
|
+
- test/data/repos/conf/svnserve.conf
|
51
|
+
- test/data/repos/db/current
|
52
|
+
- test/data/repos/db/format
|
53
|
+
- test/data/repos/db/fs-type
|
54
|
+
- test/data/repos/db/revprops
|
55
|
+
- test/data/repos/db/revs
|
56
|
+
- test/data/repos/db/transactions
|
57
|
+
- test/data/repos/db/uuid
|
58
|
+
- test/data/repos/db/write-lock
|
59
|
+
- test/data/repos/db/revprops/0
|
60
|
+
- test/data/repos/db/revprops/1
|
61
|
+
- test/data/repos/db/revprops/2
|
62
|
+
- test/data/repos/db/revprops/3
|
63
|
+
- test/data/repos/db/revs/0
|
64
|
+
- test/data/repos/db/revs/1
|
65
|
+
- test/data/repos/db/revs/2
|
66
|
+
- test/data/repos/db/revs/3
|
67
|
+
- test/data/repos/hooks/post-commit.tmpl
|
68
|
+
- test/data/repos/hooks/post-lock.tmpl
|
69
|
+
- test/data/repos/hooks/post-revprop-change.tmpl
|
70
|
+
- test/data/repos/hooks/post-unlock.tmpl
|
71
|
+
- test/data/repos/hooks/pre-commit.tmpl
|
72
|
+
- test/data/repos/hooks/pre-lock.tmpl
|
73
|
+
- test/data/repos/hooks/pre-revprop-change.tmpl
|
74
|
+
- test/data/repos/hooks/pre-unlock.tmpl
|
75
|
+
- test/data/repos/hooks/start-commit.tmpl
|
76
|
+
- test/data/repos/locks/db-logs.lock
|
77
|
+
- test/data/repos/locks/db.lock
|
78
|
+
test_files:
|
79
|
+
- test/test_all.rb
|
80
|
+
rdoc_options: []
|
81
|
+
extra_rdoc_files: []
|
82
|
+
executables:
|
83
|
+
- svnlog
|
84
|
+
extensions: []
|
85
|
+
requirements: []
|
86
|
+
dependencies:
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: ferret
|
89
|
+
version_requirement:
|
90
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
91
|
+
requirements:
|
92
|
+
-
|
93
|
+
- ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 0.9.0
|
96
|
+
version:
|