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/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
@@ -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
@@ -0,0 +1,8 @@
1
+ # $Id$
2
+
3
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
4
+
5
+ describe Svnbranch do
6
+ end
7
+
8
+ # 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