svnbranch 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +47 -0
- data/License.txt +22 -0
- data/Manifest.txt +26 -0
- data/README.txt +74 -0
- data/Rakefile +23 -0
- data/TODO.txt +3 -0
- data/bin/svnbranch +848 -0
- data/lib/svnbranch.rb +56 -0
- data/man1/Makefile +19 -0
- data/man1/svnbranch.1 +526 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/svnbranch_spec.rb +8 -0
- data/tasks/ann.rake +81 -0
- data/tasks/bones.rake +21 -0
- data/tasks/gem.rake +126 -0
- data/tasks/git.rake +41 -0
- data/tasks/manifest.rake +49 -0
- data/tasks/notes.rake +28 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +57 -0
- data/tasks/setup.rb +268 -0
- data/tasks/spec.rake +55 -0
- data/tasks/svn.rake +48 -0
- data/tasks/test.rake +38 -0
- data/test/test_svnbranch.rb +0 -0
- metadata +92 -0
data/lib/svnbranch.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# $Id$
|
2
|
+
|
3
|
+
# Equivalent to a header guard in C/C++
|
4
|
+
# Used to prevent the class/module from being loaded more than once
|
5
|
+
unless defined? Svnbranch
|
6
|
+
|
7
|
+
module Svnbranch
|
8
|
+
|
9
|
+
# :stopdoc:
|
10
|
+
VERSION = '0.2.0'
|
11
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
12
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
13
|
+
# :startdoc:
|
14
|
+
|
15
|
+
# Returns the version string for the library.
|
16
|
+
#
|
17
|
+
def self.version
|
18
|
+
VERSION
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the library path for the module. If any arguments are given,
|
22
|
+
# they will be joined to the end of the libray path using
|
23
|
+
# <tt>File.join</tt>.
|
24
|
+
#
|
25
|
+
def self.libpath( *args )
|
26
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, *args)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the lpath for the module. If any arguments are given,
|
30
|
+
# they will be joined to the end of the path using
|
31
|
+
# <tt>File.join</tt>.
|
32
|
+
#
|
33
|
+
def self.path( *args )
|
34
|
+
args.empty? ? PATH : ::File.join(PATH, *args)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Utility method used to rquire all files ending in .rb that lie in the
|
38
|
+
# directory below this file that has the same name as the filename passed
|
39
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
40
|
+
# the _filename_ does not have to be equivalent to the directory.
|
41
|
+
#
|
42
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
43
|
+
dir ||= ::File.basename(fname, '.*')
|
44
|
+
search_me = ::File.expand_path(
|
45
|
+
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
46
|
+
|
47
|
+
Dir.glob(search_me).sort.each {|rb| require rb}
|
48
|
+
end
|
49
|
+
|
50
|
+
end # module Svnbranch
|
51
|
+
|
52
|
+
Svnbranch.require_all_libs_relative_to __FILE__
|
53
|
+
|
54
|
+
end # unless defined?
|
55
|
+
|
56
|
+
# EOF
|
data/man1/Makefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
all: text ps html
|
2
|
+
|
3
|
+
text:
|
4
|
+
man ./svnbranch.1
|
5
|
+
# nroff -man svnbranch.1 | less
|
6
|
+
|
7
|
+
ps: svnbranch.ps
|
8
|
+
|
9
|
+
html: svnbranch.html
|
10
|
+
|
11
|
+
clean:
|
12
|
+
rm svnbranch.ps svnbranch.html
|
13
|
+
|
14
|
+
svnbranch.ps: svnbranch.1
|
15
|
+
groff -man svnbranch.1 > svnbranch.ps
|
16
|
+
open svnbranch.ps
|
17
|
+
|
18
|
+
svnbranch.html: svnbranch.1
|
19
|
+
groff -man -Thtml svnbranch.1 > svnbranch.html
|
data/man1/svnbranch.1
ADDED
@@ -0,0 +1,526 @@
|
|
1
|
+
.de EX
|
2
|
+
.nf
|
3
|
+
.in +0.5i
|
4
|
+
\fB\\$1\fP\\$2
|
5
|
+
.in -0.5i
|
6
|
+
.ad
|
7
|
+
.fi
|
8
|
+
..
|
9
|
+
.de CW
|
10
|
+
\&\f(CW\\$1\fP\\$2
|
11
|
+
..
|
12
|
+
.TH SVNBRANCH 1 "Karrick S. McDermott"
|
13
|
+
.
|
14
|
+
.SH NAME
|
15
|
+
svnbranch \- Subversion branching (made easy)
|
16
|
+
.SH SYNOPSIS
|
17
|
+
.BR svnbranch " [ " \-h " | " \-\-help " | " help " ] "
|
18
|
+
.br
|
19
|
+
.BR svnbranch " [ " \-d " | " \-f " | " \-s " | " \-v " | " \-q " ] "
|
20
|
+
\fBcreate\fP \fInew-branch\fP [ \fIsub-branch\fP ]
|
21
|
+
.br
|
22
|
+
.BR svnbranch " [ " \-d " | " \-f " | " \-v " | " \-q " ] "
|
23
|
+
\fBclose
|
24
|
+
.br
|
25
|
+
.BR svnbranch " [ " \-d " | " \-f " | " \-v " | " \-q " ] "
|
26
|
+
\fBmerge\fP \fImerge-branch\fP [ \fIsub-branch\fP ]
|
27
|
+
.br
|
28
|
+
.BR svnbranch " [ " \-d " | " \-f " | " \-v " | " \-q " ] "
|
29
|
+
\fBdelete\fP \fIdoomed-branch\fP [ \fIsub-branch\fP ]
|
30
|
+
.br
|
31
|
+
.BR svnbranch " [ " \-d " | " \-f " | " \-v " | " \-q " ] "
|
32
|
+
\fBswitch\fP \fIswitch-branch\fP [ \fIsub-branch\fP ]
|
33
|
+
.br
|
34
|
+
.SH DESCRIPTION
|
35
|
+
.PP
|
36
|
+
.CW Svnbranch
|
37
|
+
is a program that can assist with managing Subversion branches.
|
38
|
+
.PP
|
39
|
+
.CW Svnbranch
|
40
|
+
operates in five basic modes:
|
41
|
+
.BR create ", " close ", "
|
42
|
+
.BR merge ", " delete ", and " switch .
|
43
|
+
.
|
44
|
+
Most of the time, you will use the
|
45
|
+
.BR create ", " close ", and "
|
46
|
+
.B merge
|
47
|
+
features to work with Subversion repositories.
|
48
|
+
.
|
49
|
+
The \fBswitch\fP mode is used to change the current Subversion
|
50
|
+
\fIworking directory\fP to use a different existing branch from the Subversion
|
51
|
+
server.
|
52
|
+
.
|
53
|
+
The \fBdelete\fP mode is considered advanced usage, and a detailed
|
54
|
+
understanding of the warnings below is recommended prior to use.
|
55
|
+
.
|
56
|
+
.SH OPTIONS
|
57
|
+
.TP 5
|
58
|
+
.B \-d
|
59
|
+
Display debugging information.
|
60
|
+
.I This can get fairly lengthly and quickly obscures overall
|
61
|
+
.I program progress.
|
62
|
+
.
|
63
|
+
.TP 5
|
64
|
+
.B \-f
|
65
|
+
Forces
|
66
|
+
.CW Svnbranch
|
67
|
+
to perform the next action, even if an automatic fail-safe protection
|
68
|
+
feature would prevent the action from taking place.
|
69
|
+
.
|
70
|
+
This can be used during a \fBcreate\fP operation, to create a new branch
|
71
|
+
regardless of whether there are uncommitted files in your repository.
|
72
|
+
.
|
73
|
+
It can also be used dureing a \fBclose\fP operation, to delete the
|
74
|
+
\fI...\fP/\fBtags\fP/\fItest-branch\fP\fB-POST\fP directory from the
|
75
|
+
Subversion server and create a new one.
|
76
|
+
.
|
77
|
+
.TP 5
|
78
|
+
.BR "\-h" " | " "\-\-help"
|
79
|
+
Display
|
80
|
+
.CW Svnbranch's " man page using the system \fBman\fP utilitiy."
|
81
|
+
.
|
82
|
+
.I This is necessary because the
|
83
|
+
.B gem
|
84
|
+
.I utility does not install man pages.
|
85
|
+
.
|
86
|
+
.TP 5
|
87
|
+
.B \-q
|
88
|
+
Causes
|
89
|
+
.CW Svnbranch
|
90
|
+
to refrain from displaying any information unless there is an error
|
91
|
+
or warning.
|
92
|
+
.
|
93
|
+
.I "Note: If there"
|
94
|
+
.B is
|
95
|
+
.I "an error, a full back-trace will"
|
96
|
+
.I "be displayed for diagnostic purposes."
|
97
|
+
.
|
98
|
+
.TP 5
|
99
|
+
.B \-s
|
100
|
+
Used with the \fBcreate\fP mode.
|
101
|
+
.
|
102
|
+
Causes
|
103
|
+
.CW Svnbranch
|
104
|
+
to re-use the Subversion \fIworking directory\fP for the new branch,
|
105
|
+
instead of recursively copying the directory to a new location.
|
106
|
+
.
|
107
|
+
This is most useful when working with an extremely large repository,
|
108
|
+
but it limits your flexibility to quickly switch from one branch to another
|
109
|
+
once changes have been made in the branch \fIworking directory\fP.
|
110
|
+
.
|
111
|
+
.TP 5
|
112
|
+
.B \-v
|
113
|
+
Display verbose information concerning the operations that
|
114
|
+
.CW Svnbranch
|
115
|
+
is performing.
|
116
|
+
.
|
117
|
+
.I This is the default level of verbosity.
|
118
|
+
.
|
119
|
+
.SH MODES
|
120
|
+
.TP 5
|
121
|
+
.B create
|
122
|
+
Used to create a new branch on the Subversion repository derived from the
|
123
|
+
branch\(emor trunk\(emof the current Subversion \fIworking directory\fP.
|
124
|
+
.
|
125
|
+
.TP 5
|
126
|
+
.B close
|
127
|
+
Used to mark completion of changes on the present branch.
|
128
|
+
.
|
129
|
+
.TP 5
|
130
|
+
.B merge
|
131
|
+
Used to merge changes from a previously closed Subverion branch into the
|
132
|
+
current \fIworking directory\fP.
|
133
|
+
.
|
134
|
+
It is highly recommended that after merging, that you re-compile, and
|
135
|
+
test your project before re-committing changes back to the Subversion
|
136
|
+
server.
|
137
|
+
.
|
138
|
+
.B It is not safe to re-merge a previously merged branch into the same
|
139
|
+
.B working directory more than once.
|
140
|
+
.
|
141
|
+
.TP 5
|
142
|
+
.B delete
|
143
|
+
Used to remove any and all trace of the specified branch from the Subversion
|
144
|
+
repository without any further prompting or warnings.
|
145
|
+
.
|
146
|
+
This amounts to the three directories on the Subversion server at
|
147
|
+
\fBbranches\fP/\fIdoomed-branch\fP,
|
148
|
+
\fBtags\fP/\fIdoomed-branch\fP\fB-PRE\fP, and
|
149
|
+
\fBtags\fP/\fIdoomed-branch\fP\fB-POST\fP.
|
150
|
+
.
|
151
|
+
.TP 5
|
152
|
+
.B help
|
153
|
+
Synonym for \fB--help\fP.
|
154
|
+
.
|
155
|
+
.TP 5
|
156
|
+
.B switch
|
157
|
+
Used to switch the current \fIworking directory\fP to a different existing
|
158
|
+
branch on the Subversion server.
|
159
|
+
.
|
160
|
+
.SH SAFETY
|
161
|
+
.CW Svnbranch
|
162
|
+
performs systematic tests on the status of both your \fIworking directory\fP
|
163
|
+
and the Subversion server to maintain a logically consistent state in both
|
164
|
+
places.
|
165
|
+
.
|
166
|
+
If
|
167
|
+
.CW Svnbranch
|
168
|
+
detects an unusual situation, it will display an error message,
|
169
|
+
.IR "(see DIAGNOSTIS below)" ,
|
170
|
+
then aborts the process prior to making any changes.
|
171
|
+
.
|
172
|
+
.SH EXAMPLE WORK-FLOW
|
173
|
+
.PP
|
174
|
+
For the purposes of the following description, the phrase
|
175
|
+
.I "working directory"
|
176
|
+
refers to your current working directory that has been checked out
|
177
|
+
from a repository on the Subversion server:
|
178
|
+
.
|
179
|
+
.sp
|
180
|
+
.EX "svn co https://www.example.com/svn/myproject/trunk ~/myproject/trunk"
|
181
|
+
.sp
|
182
|
+
.CW Svnbranch
|
183
|
+
is invoked from within the \fIworking directory\fP, corresponding to either a
|
184
|
+
repository trunk or a branch.
|
185
|
+
.
|
186
|
+
Note, there is no directory name requirement for the \fIworking
|
187
|
+
directory\fP name, whether you are working from the trunk or a branch.
|
188
|
+
.
|
189
|
+
The starting directory could easily have been
|
190
|
+
.CW "~/myproject",
|
191
|
+
and the process would have worked as expected.
|
192
|
+
.sp
|
193
|
+
.EX "cd ~/myproject/trunk"
|
194
|
+
.sp
|
195
|
+
When using the \fBcreate\fP mode,
|
196
|
+
.CW Svnbranch
|
197
|
+
will create a branch on the Subversion server, and create a tag on the
|
198
|
+
Subversion server to mark the commencement of work on the new branch.
|
199
|
+
.
|
200
|
+
Finally, it will copy the files on your local system to allow you to work
|
201
|
+
in the newly created branch.
|
202
|
+
.sp
|
203
|
+
.EX "svnbranch create BUG-1234"
|
204
|
+
.sp
|
205
|
+
Change your \fIworking directory\fP to the newly created directory on your
|
206
|
+
local system:
|
207
|
+
.sp
|
208
|
+
.EX "cd ../BUG-1234"
|
209
|
+
.EX "..."
|
210
|
+
.sp
|
211
|
+
Edit, compile, \fItest\fP, and repeat until the bug is eliminated.
|
212
|
+
.
|
213
|
+
After testing the changes, commit them back to the repository from
|
214
|
+
the \fIworking directory\fP:
|
215
|
+
.sp
|
216
|
+
.EX "svn commit -m 'removed memory leak by calling free() in foo().'"
|
217
|
+
.sp
|
218
|
+
Then tag the end of the branch by using the \fBclose\fP mode of operation:
|
219
|
+
.sp
|
220
|
+
.EX "svnbranch close"
|
221
|
+
.sp
|
222
|
+
When you desire to merge the changes from a branch back into either
|
223
|
+
the trunk or a different branch, simply change your
|
224
|
+
\fIworking directory\fP to the desired branch and have
|
225
|
+
.CW Svnbranch
|
226
|
+
pull the branch changes from the Subversion server:
|
227
|
+
.sp
|
228
|
+
.EX "cd ../trunk"
|
229
|
+
.EX "svnbranch merge BUG-1234"
|
230
|
+
.EX "..."
|
231
|
+
.sp
|
232
|
+
.BR Note :
|
233
|
+
The merge of the changes from the specified branch back to the Subversion
|
234
|
+
repository has not happened yet.
|
235
|
+
.
|
236
|
+
.sp
|
237
|
+
You should compile and test the merged changes in this
|
238
|
+
\fIworking directory\fP to ensure the changes are effective in this
|
239
|
+
directory as well.
|
240
|
+
.
|
241
|
+
.I This is even more important in a multi-user development environment.
|
242
|
+
.sp
|
243
|
+
After testing reveals no bugs, Subversion is used to merge the revised
|
244
|
+
source code back into the source code maintained by the Subversion
|
245
|
+
server:
|
246
|
+
.sp
|
247
|
+
.EX "svn commit -m 'Merged bug fix from [BUG-1234] branch into [trunk].'"
|
248
|
+
.sp
|
249
|
+
You can merge the changes into various branches.
|
250
|
+
.
|
251
|
+
For example, here the changes are merged from the same bug fix to a maintenance
|
252
|
+
branch:
|
253
|
+
.sp
|
254
|
+
.EX "cd ../2.1-maint"
|
255
|
+
.EX "svnbranch merge BUG-1234"
|
256
|
+
.EX "...(testing)..."
|
257
|
+
.EX "svn commit -m 'Merged bug fix from [BUG-1234] branch into [2.1-maint].'"
|
258
|
+
.sp
|
259
|
+
.SH EXAMPLE WORK-FLOW (Using Switch Mode)
|
260
|
+
.PP
|
261
|
+
When working with extremely large repositories, the normal \fBcreate\fP mode
|
262
|
+
above can take quite a long time to copy files on your local system.
|
263
|
+
.
|
264
|
+
In this case, you can \fBcreate\fP a new branch, instructing
|
265
|
+
.CW Svnbranch
|
266
|
+
to re-use the current \fIworking directory\fP instead of copying the
|
267
|
+
directory hierarchy:
|
268
|
+
.
|
269
|
+
.sp
|
270
|
+
.EX "svnbranch -s create hash-test"
|
271
|
+
.EX "..."
|
272
|
+
.sp
|
273
|
+
At the conclusion of the above command, a new branch has been created on
|
274
|
+
the Subversion server, and your \fIworking directory\fP has been switched
|
275
|
+
to that new branch.
|
276
|
+
.
|
277
|
+
There is no need to change directories to begin work, because
|
278
|
+
.CW Svnbranch
|
279
|
+
did not create a new directory.
|
280
|
+
.
|
281
|
+
After changes are complete, tested, and committed, the branch may be
|
282
|
+
closed as normal:
|
283
|
+
.sp
|
284
|
+
.EX "svn commit -m 'improved hash method working and tested'"
|
285
|
+
.EX "svnbranch close"
|
286
|
+
.sp
|
287
|
+
Then switch back to your previous branch using the \fBswitch\fP
|
288
|
+
mode and pull the changes from the branch into your \fIworking directory\fP:
|
289
|
+
.
|
290
|
+
.sp
|
291
|
+
.EX "svnbranch switch trunk"
|
292
|
+
.EX "svnbranch merge hash-test"
|
293
|
+
.EX "..."
|
294
|
+
.sp
|
295
|
+
Once again, you will have to compile and test your program.
|
296
|
+
.
|
297
|
+
After testing is complete, commit your changes to the Subversion
|
298
|
+
server as you normally would:
|
299
|
+
.sp
|
300
|
+
.EX "svn ci -m 'Merged [hash-test] into [trunk].'"
|
301
|
+
.SH SUB-BRANCHES
|
302
|
+
.CW Svnbranch
|
303
|
+
supports using nested hierarchical directories on the Subversion
|
304
|
+
server to organize your repository. For instance, your work environment
|
305
|
+
may require you to place all of your experimental branches in a
|
306
|
+
directory nested below your login name:
|
307
|
+
.sp
|
308
|
+
.EX "svnbranch create pat/hash-test"
|
309
|
+
.sp
|
310
|
+
Similarly, some organizations require bug-fix branches in their own
|
311
|
+
sub-directory of the repository server:
|
312
|
+
.sp
|
313
|
+
.EX "svnbranch create bug-fixes/BUG-1234"
|
314
|
+
.PP
|
315
|
+
.BR Note :
|
316
|
+
Multiple levels of sub-branches may be specified, separated by the slash,
|
317
|
+
\fB/\fP, character:
|
318
|
+
.sp
|
319
|
+
.EX "svnbranch create pat/experimental/hash-test"
|
320
|
+
.sp
|
321
|
+
This creates a branch at
|
322
|
+
\fI...\fP/\fBmyproject\fP/\fBbranches\fP/\fBpat\fP/\fBexperimental\fP/\fBhash-test\fP
|
323
|
+
on the Subversion server.
|
324
|
+
.
|
325
|
+
.SH NOTES
|
326
|
+
.IP "Outstanding changes"
|
327
|
+
.CW Svnbranch
|
328
|
+
prevents you from creating, closing, merging, or switching a branch unless you have no
|
329
|
+
outstanding file edits or changes to be checked in from your
|
330
|
+
.IR "working directory" .
|
331
|
+
.
|
332
|
+
.IP "Subversion repository requirements"
|
333
|
+
To use
|
334
|
+
.CW Svnbranch
|
335
|
+
effectively, your Subversion repository should have a
|
336
|
+
.BR trunk ", " branches ", and a " tags " directory."
|
337
|
+
.
|
338
|
+
.CW Svnbranch
|
339
|
+
will attempt to create a
|
340
|
+
.BR branches " and a " tags
|
341
|
+
directory as sibling directories to the \fBtrunk\fP directory if those
|
342
|
+
are missing on the server.
|
343
|
+
.
|
344
|
+
.CW Svnbranch
|
345
|
+
will not create a \fBtrunk\fP directory if one is not present.
|
346
|
+
.
|
347
|
+
.I Nor is a trunk directory strictly required.
|
348
|
+
.I Your responsibilities may require you to integrate bug-fixes into
|
349
|
+
.I various maintenance branches at your organization.
|
350
|
+
.I In this circumstance, you would not even need to have the \fBtrunk\fP checked
|
351
|
+
.I out.
|
352
|
+
.I Simply check out a maintenance branch, and integrate changes:
|
353
|
+
.sp
|
354
|
+
.EX "svn co https://www.example.com/svn/myproject/branches/2.1-maint ~/work"
|
355
|
+
.EX "cd ~/work"
|
356
|
+
.EX "svnbranch merge BUG-1234"
|
357
|
+
.EX "...(test)..."
|
358
|
+
.EX "svn ci -m 'Merged bug-fix [BUG-1234] into maintenance branch [2.1-maint].'"
|
359
|
+
.sp
|
360
|
+
.IP "Creating\(em\fBRsync\fP"
|
361
|
+
For efficiency purposes,
|
362
|
+
.CW Svnbranch
|
363
|
+
attempts to use the \fBRsync\fP utility to copy the files on the local
|
364
|
+
system when creating a new branch.
|
365
|
+
.
|
366
|
+
If
|
367
|
+
.CW Svnbranch
|
368
|
+
cannot find the \fBRsync\fP utility on the system,
|
369
|
+
.CW Svnbranch
|
370
|
+
will use standard file-system API calls, via \fBRuby\fP's
|
371
|
+
.B FileUtils
|
372
|
+
library, to create the \fIworking directory\fP for the new
|
373
|
+
branch, clobbering over any directory already present with the same name.
|
374
|
+
.
|
375
|
+
.IP "Closing"
|
376
|
+
Do not use any branch or sub-branch identifiers for the \fBclose\fP
|
377
|
+
mode of operation.
|
378
|
+
.
|
379
|
+
.CW Svnbranch
|
380
|
+
will learn these from inspecting your current \fIworking directory\fP.
|
381
|
+
.
|
382
|
+
Any attempts to specify a branch or sub-branch name for a \fBclose\fP
|
383
|
+
operation will result in an error message being displayed.
|
384
|
+
.
|
385
|
+
No changes will be made to the Subversion server repositories in this
|
386
|
+
event.
|
387
|
+
.
|
388
|
+
.SH CAVEATS
|
389
|
+
.IP "Creating"
|
390
|
+
Results are not determined if you create a new branch from a directory
|
391
|
+
that is not the root directory of a project.
|
392
|
+
.
|
393
|
+
.IP "Creating a branch of a \fIlarge repository\fP"
|
394
|
+
For large Subversion repositories, creating a new branch can take a significant
|
395
|
+
amount of time as the repository files are pulled from the Subversion server.
|
396
|
+
.
|
397
|
+
.CW Svnbranch
|
398
|
+
mitigates this by splitting the operation into three steps, significantly
|
399
|
+
improving performance:
|
400
|
+
.in +0.5i
|
401
|
+
.sp
|
402
|
+
First,
|
403
|
+
.CW Svnbranch
|
404
|
+
instructs the Subversion server to duplicate the repository remotely
|
405
|
+
on the server, using minimal network bandwidth.
|
406
|
+
.sp
|
407
|
+
Second, instead of checking out the new branch over the network,
|
408
|
+
.CW Svnbranch
|
409
|
+
duplicates the \fIworking directory\fP locally.
|
410
|
+
.
|
411
|
+
.CW Svnbranch
|
412
|
+
further improves performance by attempting to use the \fBRsync\fP utility
|
413
|
+
on the local system to expedite the file copy process.
|
414
|
+
.
|
415
|
+
.I (See NOTES above.)
|
416
|
+
.sp
|
417
|
+
Third,
|
418
|
+
.CW Svnbranch
|
419
|
+
instructs the local system to change which remote repository is pointed to by
|
420
|
+
the newly created \fIworking directory\fP.
|
421
|
+
.
|
422
|
+
.sp
|
423
|
+
.in -0.5i
|
424
|
+
For all but the largest of working directories, this process is relatively
|
425
|
+
fast.
|
426
|
+
.
|
427
|
+
However, during
|
428
|
+
.CW Svnbranch
|
429
|
+
development, a repository larger than 8 gigabytes was routinely used
|
430
|
+
for testing.
|
431
|
+
.
|
432
|
+
The delay was noticeable\(emtaking approximately 10 minutes to complete.
|
433
|
+
.
|
434
|
+
.SH WARNING
|
435
|
+
.IP "Deleteing a branch"
|
436
|
+
Deleteing a branch is considered an advanced mode of operation for
|
437
|
+
.IR Svnbranch ,
|
438
|
+
and it should be done only with a detailed understanding of how
|
439
|
+
.CW Svnbranch
|
440
|
+
manages branches on the Subversion repository server.
|
441
|
+
.
|
442
|
+
.sp
|
443
|
+
When
|
444
|
+
.CW Svnbranch
|
445
|
+
creates a new branch, it creates a copy of the
|
446
|
+
working branch in the \fBbranches\fP directory on the Subversion server.
|
447
|
+
.
|
448
|
+
Then creates a tag to mark the start of changes in this new branch in the
|
449
|
+
\fBtags\fP directory.
|
450
|
+
.
|
451
|
+
Later, when someone \fBclose\fPs a branch,
|
452
|
+
.CW Svnbranch
|
453
|
+
will create a new tag to mark the end of changes in the \fBtags\fP directory.
|
454
|
+
.
|
455
|
+
.sp
|
456
|
+
If for some reason you desire to remove all traces of the specified
|
457
|
+
branch from the Subversion repository, the \fBdelete\fP operation can be used
|
458
|
+
to delete the relevant directories from the Subversion repository.
|
459
|
+
.
|
460
|
+
When invoked with the \fBdelete\fP mode,
|
461
|
+
.CW Svnbranch
|
462
|
+
will remove any and all of these three directories from the Subversion
|
463
|
+
repository without any further prompting or warnings.
|
464
|
+
.
|
465
|
+
.SH DIAGNOSTICS
|
466
|
+
.PP
|
467
|
+
.CW Svnbranch
|
468
|
+
uses the \fBWatcher\fP Ruby gem,
|
469
|
+
which provides a combined logging and condition-handling
|
470
|
+
mechanism for Ruby programs.
|
471
|
+
.
|
472
|
+
As such, when an error or warning occurs,
|
473
|
+
.CW Svnbranch
|
474
|
+
will display all the previous log messages that had been masked by
|
475
|
+
.BR Watcher .
|
476
|
+
.
|
477
|
+
.sp
|
478
|
+
Although not usually needed, you may direct
|
479
|
+
.CW Svnbranch
|
480
|
+
to display more verbose status messages, by invoking it with
|
481
|
+
the \fB\-d\fP command line option.
|
482
|
+
.
|
483
|
+
.SH BUGS
|
484
|
+
.IP Merging
|
485
|
+
It is not safe to re-merge a previously merged branch into the same
|
486
|
+
working directory more than once.
|
487
|
+
.
|
488
|
+
.IP "Runtime Errors"
|
489
|
+
.CW Svnbranch
|
490
|
+
makes all practical attempts to ensure the Subversion server's
|
491
|
+
repositories are left in a logically correct state in the event of a
|
492
|
+
runtime error.
|
493
|
+
.
|
494
|
+
If
|
495
|
+
.CW Svnbranch
|
496
|
+
aborts a process in the middle of command due to an error or its
|
497
|
+
process is stopped, the Subversion repository may be in an inconsistant state.
|
498
|
+
.
|
499
|
+
.sp
|
500
|
+
For instance, say that the user hits Ctrl-C during a create process, after
|
501
|
+
.CW Svnbranch
|
502
|
+
has created
|
503
|
+
\fI...\fP/\fBmyproject\fP/\fBbranches\fP/\fItest-branch\fP, but before
|
504
|
+
it has created
|
505
|
+
\fI...\fP/\fBmyproject\fP/\fBtags\fP/\fItest-branch\fP\fB-PRE\fP.
|
506
|
+
.
|
507
|
+
In this event, you may have to use the below command to clean up the repository
|
508
|
+
on the Subversion server, then try again:
|
509
|
+
.sp
|
510
|
+
.EX "svnbranch delete \fItest-branch\fP"
|
511
|
+
.sp
|
512
|
+
.SH "SEE ALSO"
|
513
|
+
.TP 5
|
514
|
+
.BR svn (1)
|
515
|
+
Subversion command line client tool
|
516
|
+
.TP 5
|
517
|
+
.BR svnadmin (1)
|
518
|
+
Subversion repository administration tool
|
519
|
+
.TP 5
|
520
|
+
.BR rsync (1)
|
521
|
+
A fast, versatile, remote (and local) file-copying tool
|
522
|
+
.TP 5
|
523
|
+
.B Watcher
|
524
|
+
A gem for logging and condition-handling of Ruby programs.
|
525
|
+
.SH AUTHOR
|
526
|
+
Karrick S. McDermott
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# $Id$
|
2
|
+
|
3
|
+
require File.expand_path(
|
4
|
+
File.join(File.dirname(__FILE__), %w[.. lib svnbranch]))
|
5
|
+
|
6
|
+
Spec::Runner.configure do |config|
|
7
|
+
# == Mock Framework
|
8
|
+
#
|
9
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
10
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
11
|
+
#
|
12
|
+
# config.mock_with :mocha
|
13
|
+
# config.mock_with :flexmock
|
14
|
+
# config.mock_with :rr
|
15
|
+
end
|
16
|
+
|
17
|
+
# EOF
|
data/tasks/ann.rake
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# $Id$
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bones/smtp_tls'
|
5
|
+
rescue LoadError
|
6
|
+
require 'net/smtp'
|
7
|
+
end
|
8
|
+
require 'time'
|
9
|
+
|
10
|
+
namespace :ann do
|
11
|
+
|
12
|
+
# A prerequisites task that all other tasks depend upon
|
13
|
+
task :prereqs
|
14
|
+
|
15
|
+
file PROJ.ann.file do
|
16
|
+
ann = PROJ.ann
|
17
|
+
puts "Generating #{ann.file}"
|
18
|
+
File.open(ann.file,'w') do |fd|
|
19
|
+
fd.puts("#{PROJ.name} version #{PROJ.version}")
|
20
|
+
fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
|
21
|
+
fd.puts(" #{PROJ.url}") if PROJ.url.valid?
|
22
|
+
fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
|
23
|
+
fd.puts
|
24
|
+
fd.puts("== DESCRIPTION")
|
25
|
+
fd.puts
|
26
|
+
fd.puts(PROJ.description)
|
27
|
+
fd.puts
|
28
|
+
fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
|
29
|
+
fd.puts
|
30
|
+
ann.paragraphs.each do |p|
|
31
|
+
fd.puts "== #{p.upcase}"
|
32
|
+
fd.puts
|
33
|
+
fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
|
34
|
+
fd.puts
|
35
|
+
end
|
36
|
+
fd.puts ann.text if ann.text
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Create an announcement file"
|
41
|
+
task :announcement => ['ann:prereqs', PROJ.ann.file]
|
42
|
+
|
43
|
+
desc "Send an email announcement"
|
44
|
+
task :email => ['ann:prereqs', PROJ.ann.file] do
|
45
|
+
ann = PROJ.ann
|
46
|
+
from = ann.email[:from] || PROJ.email
|
47
|
+
to = Array(ann.email[:to])
|
48
|
+
|
49
|
+
### build a mail header for RFC 822
|
50
|
+
rfc822msg = "From: #{from}\n"
|
51
|
+
rfc822msg << "To: #{to.join(',')}\n"
|
52
|
+
rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
|
53
|
+
rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
|
54
|
+
rfc822msg << "\n"
|
55
|
+
rfc822msg << "Date: #{Time.new.rfc822}\n"
|
56
|
+
rfc822msg << "Message-Id: "
|
57
|
+
rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
|
58
|
+
rfc822msg << File.read(ann.file)
|
59
|
+
|
60
|
+
params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
|
61
|
+
ann.email[key]
|
62
|
+
end
|
63
|
+
|
64
|
+
params[3] = PROJ.email if params[3].nil?
|
65
|
+
|
66
|
+
if params[4].nil?
|
67
|
+
STDOUT.write "Please enter your e-mail password (#{params[3]}): "
|
68
|
+
params[4] = STDIN.gets.chomp
|
69
|
+
end
|
70
|
+
|
71
|
+
### send email
|
72
|
+
Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
|
73
|
+
end
|
74
|
+
end # namespace :ann
|
75
|
+
|
76
|
+
desc 'Alias to ann:announcement'
|
77
|
+
task :ann => 'ann:announcement'
|
78
|
+
|
79
|
+
CLOBBER << PROJ.ann.file
|
80
|
+
|
81
|
+
# EOF
|