1#!/usr/bin/perl
2# Copyright (C) 2008-2009, Mark Glines.  See "LICENSE".
3use strict;
4use warnings;
5
6use App::SVN::Bisect;
7use Getopt::Long qw(:config require_order);
8
9my $min     = undef;
10my $max     = undef;
11my $back    = 0;
12my $verbose = 0;
13my $help    = 0;
14my $version = 0;
15
16GetOptions(
17    "min=s"   => \$min,
18    "max=s"   => \$max,
19    "back"    => \$back,
20    "verbose" => \$verbose,
21    "version" => \$version,
22    "help"    => \$help,
23);
24
25die("Value \"$min\" invalid for option min (revision expected)\n")
26    if(defined($min) && $min !~ /^r?\d+$/);
27die("Value \"$max\" invalid for option min (revision expected)\n")
28    if(defined($max) && $max !~ /^r?\d+$/);
29
30if($version) {
31    print("This is svn-bisect version ", $App::SVN::Bisect::VERSION, ".\n");
32    exit(0);
33}
34
35unshift(@ARGV, "help") if $help;
36
37my $action = shift;
38
39my $bisect = App::SVN::Bisect->new(
40    Action  => $action,
41    Min     => $min,
42    Max     => $max,
43    Verbose => $verbose,
44    Back    => $back
45);
46$bisect->do_something_intelligent(@ARGV);
47
48
49=head1 NAME
50
51svn-bisect
52
53=head1 SYNOPSIS
54
55    $ svn-bisect --min 25000 --max 26000 start
56    $ svn-bisect bad
57    $ svn-bisect bad
58    $ svn-bisect good
59    [etc etc]
60    $ svn-bisect reset
61
62
63=head1 DESCRIPTION
64
65This tool's purpose is to help you determine which revision of a subversion
66repository contains a change.  It does this by employing a binary search.
67It will manage the current revision of your checkout directory, and narrow
68in on the target revision, as you give it clues about the current revision
69such as "before" (this revision is before the one you want) or "after" (this
70revision is after the one you want).
71
72Start a bisect session with the "start" command.  Then, walk the binary tree
73by using the "before" and "after" commands.  When you are done, the tool will
74tell you the target revision.
75
76The most common usage scenario is finding out which rev a bug was introduced
77in.  For this purpose, some command aliases have been added: if the current
78revision contains the bug, you can use the "bad" command (meaning, this
79revision is "after" the change you want to find), otherwise use the "good"
80command (meaning, this revision is "before" the change you want to find).
81
82All commands should be run from within a subversion checkout directory.  After
83a "svn-bisect start", all subsequent svn-bisect commands need to be run from
84that same directory.
85
86
87=head1 OPTIONS
88
89Options MUST be specified before subcommands, on the command line.  Options
90specified after the subcommand will be passed to the subcommand; this is
91currently only useful for the "run" subcommand.
92
93=over 4
94
95=item --help
96
97Use anywhere.  Output a command list, or specific help for the given command.
98
99=item --version
100
101Use anywhere.  Tells you my version number.
102
103=item --verbose
104
105Use anywhere.  Enable some additional informational output.
106
107=item --min
108
109Use with "start".  Specify the beginning revision of the range.
110
111=item --max
112
113Use with "start".  Specify the ending revision of the range.
114
115=item --back
116
117Use with "reset".  Restores the original repository version.
118
119=back
120
121
122=head1 SUBCOMMANDS
123
124=head2 start
125
126    svn-bisect [--min M] [--max N] start
127
128Start a new bisect session.  If --min isn't specified, you can specify it later
129with the "good" command.  If --max isn't specified, you can specify it later
130with the "bad" command.
131
132=head2 after
133
134    svn-bisect after [revision]
135    or: svn-bisect bad [revision]
136
137Inform svn-bisect that the specified revision is *after* the change we're
138looking for.  If you don't specify a revision number, the current revision of
139the working tree is used.  If you are looking for the rev which introduced a bug
140(which is the common case), the alias "bad" might be easier to remember.
141
142=head2 before
143
144    svn-bisect before [revision]
145    or: svn-bisect good [revision]
146
147Inform svn-bisect that the specified revision is *before* the change we're
148looking for.  If you don't specify a revision number, the current revision of
149the working tree is used.  If you are looking for the rev which introduced a bug
150(which is the common case), the alias "good" might be easier to remember.
151
152=head2 skip
153
154    svn-bisect skip [<rev> [<rev>...]]
155
156Tell svn-bisect to skip the specified revision.  If no revision is specified,
157the current version of the working tree is used.  Do this if you can't determine
158whether the current revision is bad or good, if, for instance, some other
159issue prevents it from compiling successfully.
160
161You may specify more than one revision, and they will all be skipped.
162
163=head2 unskip
164
165    svn-bisect unskip <rev> [<rev>...]
166
167Tell svn-bisect to no longer skip the specified revision.  You must specify
168at least one revision to unskip.  If you specify more than one, they will
169all be unskipped.
170
171=head2 run
172
173    svn-bisect run <command> [arguments...]
174
175Runs a command repeatedly to automate the bisection process.
176
177Examples:
178
179    svn-bisect run ./mytest.sh
180    svn-bisect run test ! -f file
181
182We run the command and arguments until a conclusion is reached.  The
183command (usually a shell script) tells us about the current revision
184by way of its return code.  The following return codes are handled:
185
186    0: This revision is before the change we're looking for
187    1-124, 126-127: This revision includes the change we're looking for
188    125: This revision is untestable and should be skipped
189    any other value: The command failed to run, abort bisection.
190
191In other words, "run" will automatically find the last revision for
192which the given command returns success.  (Keep in mind that in the
193shell, "0" means "success".)
194
195The normal caveats apply.  In particular, if your script makes any
196changes, don't forget to clean up afterwards.
197
198=head2 reset
199
200    svn-bisect reset
201
202Clean up after a bisect, and return the repository to the revision it was at
203before you started.
204
205=head2 help
206
207    svn-bisect help
208    svn-bisect help start
209
210Gives you some useful descriptions and usage information.
211
212
213=head1 EXAMPLE
214
215...Because, you know, no software documentation is complete without a flashy
216screenshot, these days.
217
218So, lets say you were wondering when the subversion project added the
219"Last Changed Rev:" line to the output of "svn info".  Determining the
220existence of this change is a straightforward matter of searching for the
221text string... if a result was found, the current revision is "after",
222otherwise it was "before".  So a bisect looks like this:
223
224    $ svn co http://svn.apache.org/repos/asf/subversion/trunk/subversion
225    [snip lots of subversion checkout spam]
226    Checked out revision 980012.
227
228    $ cd subversion
229
230    $ ack --nocolor --nogroup 'Last Changed Rev'
231    svn/info-cmd.c:362:    SVN_ERR(svn_cmdline_printf(pool, _("Last Changed Rev: %ld\n"),
232    tests/cmdline/depth_tests.py:2056:      'Last Changed Rev'   : '^1$',
233    tests/cmdline/upgrade_tests.py:387:      'Last Changed Rev' : '7'
234    tests/cmdline/upgrade_tests.py:396:      'Last Changed Rev' : '10'
235
236    $ date
237    Wed Jul 28 06:40:03 EDT 2010
238
239    $ svn-bisect --min 0 start
240    $ svn-bisect after
241    Fetching history from r0 to r980012; it may take a while.
242    There are 24349 revs left in the pool.  Choosing r862045.
243
244    $ ack --nocolor --nogroup 'Last Changed Rev'
245    svn/info-cmd.c:348:    SVN_ERR(svn_cmdline_printf(pool, _("Last Changed Rev: %ld\n"),
246
247    $ svn-bisect after
248    There are 12174 revs left in the pool.  Choosing r845633.
249
250    $ ack --nocolor --nogroup 'Last Changed Rev'
251    clients/cmdline/info-cmd.c:153:    printf ("Last Changed Rev: %" SVN_REVNUM_T_FMT "\n", entry->cmt_rev);
252
253    $ svn-bisect after
254    There are 6087 revs left in the pool.  Choosing r840416.
255
256    $ ack --nocolor --nogroup 'Last Changed Rev'
257
258    $ svn-bisect before
259    There are 3043 revs left in the pool.  Choosing r842636.
260
261    # ack --nocolor --nogroup 'Last Changed Rev'
262    clients/cmdline/info-cmd.c:153:    printf ("Last Changed Rev: %" SVN_REVNUM_T_FMT "\n", entry->cmt_rev);
263
264    $ svn-bisect after
265    There are 1521 revs left in the pool.  Choosing r841463.
266
267    $ ack --nocolor --nogroup 'Last Changed Rev'
268
269    $ svn-bisect before
270    There are 760 revs left in the pool.  Choosing r841993.
271
272    $ ack --nocolor --nogroup 'Last Changed Rev'
273    clients/cmdline/info-cmd.c:161:        printf ("Last Changed Rev: %" SVN_REVNUM_T_FMT "\n", entry->cmt_rev);
274
275    $ svn-bisect after
276    There are 380 revs left in the pool.  Choosing r841730.
277
278    $ ack --nocolor --nogroup 'Last Changed Rev'
279
280    $ svn-bisect before
281    There are 189 revs left in the pool.  Choosing r841860.
282
283    $ ack --nocolor --nogroup 'Last Changed Rev'
284
285    $ svn-bisect before
286    There are 94 revs left in the pool.  Choosing r841933.
287
288    $ ack --nocolor --nogroup 'Last Changed Rev'
289    clients/cmdline/info-cmd.c:151:        printf ("Last Changed Rev: %" SVN_REVNUM_T_FMT "\n", entry->cmt_rev);
290
291    $ svn-bisect after
292    There are 47 revs left in the pool.  Choosing r841904.
293
294    $ ack --nocolor --nogroup 'Last Changed Rev'
295    clients/cmdline/info-cmd.c:150:        printf ("Last Changed Rev: %ld\n", entry->cmt_rev);
296
297    $ svn-bisect after
298    There are 23 revs left in the pool.  Choosing r841880.
299
300    $ ack --nocolor --nogroup 'Last Changed Rev'
301
302    $ svn-bisect before
303    There are 11 revs left in the pool.  Choosing r841890.
304
305    $ ack --nocolor --nogroup 'Last Changed Rev'
306    clients/cmdline/info-cmd.c:153:            printf ("Last Changed Rev: %ld\n", entry->cmt_rev);
307
308    $ svn-bisect after
309    There are 5 revs left in the pool.  Choosing r841883.
310
311    $ ack --nocolor --nogroup 'Last Changed Rev'
312    clients/cmdline/info-cmd.c:153:            printf ("Last Changed Rev: %ld\n", entry->cmt_rev);
313
314    $ svn-bisect after
315    There are 2 revs left in the pool.  Choosing r841882.
316
317    $ ack --nocolor --nogroup 'Last Changed Rev'
318
319    $ svn-bisect before
320    This is the end of the road!
321    The change occurred in r841883.
322
323    $ svn log -r841883
324    ------------------------------------------------------------------------
325    r841883 | rooneg | 2002-04-27 15:23:38 -0400 (Sat, 27 Apr 2002) | 30 lines
326
327    As requested by cmpilato in issue #676, add an 'svn info' command, which
328    prints out the contents of the svn_wc_entry_t for a given versioned resource.
329
330    * CHANGES
331      note the addition of the 'svn info' command.
332
333    * subversion/clients/cmdline/cl.h
334      add declaration for svn_cl__info.
335
336    * subversion/clients/cmdline/info-cmd.c
337      new file implementing the info command.
338
339    * subversion/clients/cmdline/main.c
340      hook up the info command.
341
342    * subversion/clients/cmdline/man/svn.1
343      document the info command.
344
345    * subversion/tests/clients/cmdline/getopt_tests_data/svn--help_stdout
346      update for the addition of info command.
347
348    * subversion/tests/clients/cmdline/getopt_tests_data/svn_help_stdout
349      ditto.
350
351    * subversion/tests/clients/cmdline/getopt_tests_data/svn_stderr
352      ditto.
353
354    * tools/dev/bash_completion
355      add 'info' to the tab completion.
356
357    ------------------------------------------------------------------------
358
359    $ date
360    Wed Jul 28 06:45:27 EDT 2010
361
362So, there it is.  In 5 minutes, we've learned that "Last Changed Rev:" has been
363in there since the inception of the "svn info" command itself, back in 2002.
364
365You can also provide a script command to do all of the work for you:
366
367    $ svn-bisect --min 0 --max 980012 start
368    $ svn-bisect run '! grep -r "Last Changed Rev" .'
369
370
371=head1 REQUIREMENTS
372
373This tool requires:
374
375* A computer
376
377* A brain
378
379* An installation of Perl, version 5.8 or above
380
381* The IO::All module, installed from CPAN
382
383* The YAML::Syck module, installed from CPAN
384
385* The "svn" command somewhere in your PATH, executable by the current user
386
387* A svn checkout with some history to bisect.
388
389
390=head1 AUTHOR
391
392    Mark Glines <mark-cpan@glines.org>
393
394
395=head1 REPOSITORY
396
397Browser: L<http://github.com/Infinoid/svn-bisect/>
398Clone: L<git://github.com/Infinoid/svn-bisect.git>
399
400
401=head1 THANKS
402
403* Thanks to the git-bisect author(s), for coming up with a user interface that
404  I actually like.
405
406* Thanks to Will Coleda for inspiring me to actually write and release this.
407
408* Thanks to the Parrot project for having so much random stuff going on as to
409  make a tool like this necessary.
410
411
412=head1 SEE ALSO
413
414App::SVNBinarySearch by Will Coleda: L<http://search.cpan.org/dist/App-SVNBinarySearch/>
415
416
417=head1 COPYRIGHT AND LICENSE
418
419This software is copyright (c) 2008 Mark Glines.
420
421It is distributed under the terms of the Artistic License 2.0.  For details,
422see the "LICENSE" file packaged alongside this tool.
423
424=cut
425