~svn/ubuntu/oneiric/subversion/ppa

« back to all changes in this revision

Viewing changes to subversion/svnlook/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2006-12-13 17:57:16 UTC
  • mfrom: (1.1.6 upstream) (0.1.3 etch)
  • Revision ID: james.westby@ubuntu.com-20061213175716-2ysv6z4w5dpa2r2f
Tags: 1.4.2dfsg1-2ubuntu1
* Merge with Debian unstable; remaining changes:
  - Create pot file on build.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * main.c: Subversion server inspection tool.
3
3
 *
4
4
 * ====================================================================
5
 
 * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 
5
 * Copyright (c) 2000-2006 CollabNet.  All rights reserved.
6
6
 *
7
7
 * This software is licensed as described in the file COPYING, which
8
8
 * you should have received as part of this distribution.  The terms
82
82
  };
83
83
 
84
84
/*
85
 
 * This must not have more than SVN_OPT_MAX_OPTIONS entries; if you
86
 
 * need more, increase that limit first. 
87
 
 *
88
85
 * The entire list must be terminated with an entry of nulls.
89
86
 */
90
87
static const apr_getopt_option_t options_table[] =
91
 
  {
92
 
    {"help",          'h', 0,
93
 
     N_("show help on a subcommand")},
94
 
 
95
 
    {NULL,            '?', 0,
96
 
     N_("show help on a subcommand")},
97
 
 
98
 
    {"version",       svnlook__version, 0,
99
 
     N_("show version information")},
100
 
 
101
 
    {"revision",      'r', 1,
102
 
     N_("specify revision number ARG")},
103
 
 
104
 
    {"transaction",  't', 1,
105
 
     N_("specify transaction name ARG")},
106
 
 
107
 
    {"verbose",  'v', 0,
108
 
     N_("be verbose")},
109
 
 
110
 
    {"show-ids",      svnlook__show_ids, 0,
111
 
     N_("show node revision ids for each path")},
112
 
 
113
 
    {"no-diff-deleted", svnlook__no_diff_deleted, 0,
114
 
     N_("do not print differences for deleted files")},
115
 
 
116
 
    {"no-diff-added", svnlook__no_diff_added, 0,
117
 
     N_("do not print differences for added files")},
118
 
 
119
 
    {"diff-copy-from", svnlook__diff_copy_from, 0,
120
 
     N_("print differences against the copy source")},
121
 
 
122
 
    {"revprop", svnlook__revprop_opt, 0,
123
 
     N_("operate on a revision property (use with -r or -t)")},
124
 
 
125
 
    {"full-paths", svnlook__full_paths, 0,
126
 
     N_("show full paths instead of indenting them")},
127
 
 
128
 
    {"copy-info", svnlook__copy_info, 0,
129
 
     N_("show details for copies")},
130
 
 
131
 
 
132
 
    {0,               0, 0, 0}
133
 
  };
 
88
{
 
89
  {"help",          'h', 0,
 
90
   N_("show help on a subcommand")},
 
91
 
 
92
  {NULL,            '?', 0,
 
93
   N_("show help on a subcommand")},
 
94
 
 
95
  {"version",       svnlook__version, 0,
 
96
   N_("show program version information")},
 
97
 
 
98
  {"revision",      'r', 1,
 
99
   N_("specify revision number ARG")},
 
100
 
 
101
  {"transaction",  't', 1,
 
102
   N_("specify transaction name ARG")},
 
103
 
 
104
  {"verbose",  'v', 0,
 
105
   N_("be verbose")},
 
106
 
 
107
  {"show-ids",      svnlook__show_ids, 0,
 
108
   N_("show node revision ids for each path")},
 
109
 
 
110
  {"no-diff-deleted", svnlook__no_diff_deleted, 0,
 
111
   N_("do not print differences for deleted files")},
 
112
 
 
113
  {"no-diff-added", svnlook__no_diff_added, 0,
 
114
   N_("do not print differences for added files")},
 
115
 
 
116
  {"diff-copy-from", svnlook__diff_copy_from, 0,
 
117
   N_("print differences against the copy source")},
 
118
 
 
119
  {"revprop", svnlook__revprop_opt, 0,
 
120
   N_("operate on a revision property (use with -r or -t)")},
 
121
 
 
122
  {"full-paths", svnlook__full_paths, 0,
 
123
   N_("show full paths instead of indenting them")},
 
124
 
 
125
  {"copy-info", svnlook__copy_info, 0,
 
126
   N_("show details for copies")},
 
127
 
 
128
  {0,               0, 0, 0}
 
129
};
134
130
 
135
131
 
136
132
/* Array of available subcommands.
137
133
 * The entire list must be terminated with an entry of nulls.
138
134
 */
139
135
static const svn_opt_subcommand_desc_t cmd_table[] =
140
 
  {
141
 
    {"author", subcommand_author, {0},
142
 
     N_("usage: svnlook author REPOS_PATH\n\n"
143
 
        "Print the author.\n"),
144
 
     {'r', 't'} },
145
 
    
146
 
    {"cat", subcommand_cat, {0},
147
 
     N_("usage: svnlook cat REPOS_PATH FILE_PATH\n\n"
148
 
        "Print the contents of a file.  Leading '/' on FILE_PATH is "
149
 
        "optional.\n"),
150
 
     {'r', 't'} },
151
 
    
152
 
    {"changed", subcommand_changed, {0},
153
 
     N_("usage: svnlook changed REPOS_PATH\n\n"
154
 
        "Print the paths that were changed.\n"),
155
 
     {'r', 't', svnlook__copy_info} },
156
 
    
157
 
    {"date", subcommand_date, {0},
158
 
     N_("usage: svnlook date REPOS_PATH\n\n"
159
 
        "Print the datestamp.\n"),
160
 
     {'r', 't'} },
161
 
 
162
 
    {"diff", subcommand_diff, {0},
163
 
     N_("usage: svnlook diff REPOS_PATH\n\n"
164
 
        "Print GNU-style diffs of changed files and properties.\n"),
165
 
     {'r', 't', svnlook__no_diff_deleted, svnlook__no_diff_added,
166
 
      svnlook__diff_copy_from} },
167
 
 
168
 
    {"dirs-changed", subcommand_dirschanged, {0},
169
 
     N_("usage: svnlook dirs-changed REPOS_PATH\n\n"
170
 
        "Print the directories that were themselves changed (property edits)\n"
171
 
        "or whose file children were changed.\n"),
172
 
     {'r', 't'} },
173
 
    
174
 
    {"help", subcommand_help, {"?", "h"},
175
 
     N_("usage: svnlook help [SUBCOMMAND...]\n\n"
176
 
        "Describe the usage of this program or its subcommands.\n"),
177
 
     {svnlook__version} },
178
 
 
179
 
    {"history", subcommand_history, {0},
180
 
     N_("usage: svnlook history REPOS_PATH [PATH_IN_REPOS]\n\n"
181
 
        "Print information about the history of a path in the repository (or\n"
182
 
        "the root directory if no path is supplied).\n"),
183
 
     {'r', svnlook__show_ids} },
184
 
 
185
 
    {"info", subcommand_info, {0},
186
 
     N_("usage: svnlook info REPOS_PATH\n\n"
187
 
        "Print the author, datestamp, log message size, and log message.\n"),
188
 
     {'r', 't'} },
189
 
 
190
 
    {"lock", subcommand_lock, {0},
191
 
     N_("usage: svnlook lock REPOS_PATH PATH_IN_REPOS\n\n"
192
 
        "If a lock exists on a path in the repository, describe it.\n"),
193
 
     {0} },
194
 
 
195
 
    {"log", subcommand_log, {0},
196
 
     N_("usage: svnlook log REPOS_PATH\n\n"
197
 
        "Print the log message.\n"),
198
 
     {'r', 't'} },
199
 
 
200
 
    {"propget", subcommand_pget, {"pget", "pg"},
201
 
     N_("usage: svnlook propget REPOS_PATH PROPNAME [PATH_IN_REPOS]\n\n"
202
 
        "Print the raw value of a property on a path in the repository.\n"
203
 
        "With --revprop, prints the raw value of a revision property.\n"),
204
 
     {'r', 't', svnlook__revprop_opt} },
205
 
 
206
 
    {"proplist", subcommand_plist, {"plist", "pl"},
207
 
     N_("usage: svnlook proplist REPOS_PATH [PATH_IN_REPOS]\n\n"
208
 
        "List the properties of a path in the repository, or\n"
209
 
        "with the --revprop option, revision properties.\n"
210
 
        "With -v, show the property values too.\n"),
211
 
     {'r', 't', 'v', svnlook__revprop_opt} },
212
 
 
213
 
    {"tree", subcommand_tree, {0},
214
 
     N_("usage: svnlook tree REPOS_PATH [PATH_IN_REPOS]\n\n"
215
 
        "Print the tree, starting at PATH_IN_REPOS (if supplied, at the root\n"
216
 
        "of the tree otherwise), optionally showing node revision ids.\n"),
217
 
     {'r', 't', svnlook__show_ids, svnlook__full_paths} },
218
 
 
219
 
    {"uuid", subcommand_uuid, {0},
220
 
     N_("usage: svnlook uuid REPOS_PATH\n\n"
221
 
        "Print the repository's UUID.\n"),
222
 
     {0} },
223
 
 
224
 
    {"youngest", subcommand_youngest, {0},
225
 
     N_("usage: svnlook youngest REPOS_PATH\n\n"
226
 
        "Print the youngest revision number.\n"),
227
 
     {0} },
228
 
 
229
 
    { NULL, NULL, {0}, NULL, {0} }
230
 
  };
 
136
{
 
137
  {"author", subcommand_author, {0},
 
138
   N_("usage: svnlook author REPOS_PATH\n\n"
 
139
      "Print the author.\n"),
 
140
   {'r', 't'} },
 
141
 
 
142
  {"cat", subcommand_cat, {0},
 
143
   N_("usage: svnlook cat REPOS_PATH FILE_PATH\n\n"
 
144
      "Print the contents of a file.  Leading '/' on FILE_PATH is optional.\n"),
 
145
   {'r', 't'} },
 
146
 
 
147
  {"changed", subcommand_changed, {0},
 
148
   N_("usage: svnlook changed REPOS_PATH\n\n"
 
149
      "Print the paths that were changed.\n"),
 
150
   {'r', 't', svnlook__copy_info} },
 
151
 
 
152
  {"date", subcommand_date, {0},
 
153
   N_("usage: svnlook date REPOS_PATH\n\n"
 
154
      "Print the datestamp.\n"),
 
155
   {'r', 't'} },
 
156
 
 
157
  {"diff", subcommand_diff, {0},
 
158
   N_("usage: svnlook diff REPOS_PATH\n\n"
 
159
      "Print GNU-style diffs of changed files and properties.\n"),
 
160
   {'r', 't', svnlook__no_diff_deleted, svnlook__no_diff_added,
 
161
    svnlook__diff_copy_from} },
 
162
 
 
163
  {"dirs-changed", subcommand_dirschanged, {0},
 
164
   N_("usage: svnlook dirs-changed REPOS_PATH\n\n"
 
165
      "Print the directories that were themselves changed (property edits)\n"
 
166
      "or whose file children were changed.\n"),
 
167
   {'r', 't'} },
 
168
 
 
169
  {"help", subcommand_help, {"?", "h"},
 
170
   N_("usage: svnlook help [SUBCOMMAND...]\n\n"
 
171
      "Describe the usage of this program or its subcommands.\n"),
 
172
   {0} },
 
173
 
 
174
  {"history", subcommand_history, {0},
 
175
   N_("usage: svnlook history REPOS_PATH [PATH_IN_REPOS]\n\n"
 
176
      "Print information about the history of a path in the repository (or\n"
 
177
      "the root directory if no path is supplied).\n"),
 
178
   {'r', svnlook__show_ids} },
 
179
 
 
180
  {"info", subcommand_info, {0},
 
181
   N_("usage: svnlook info REPOS_PATH\n\n"
 
182
      "Print the author, datestamp, log message size, and log message.\n"),
 
183
   {'r', 't'} },
 
184
 
 
185
  {"lock", subcommand_lock, {0},
 
186
   N_("usage: svnlook lock REPOS_PATH PATH_IN_REPOS\n\n"
 
187
      "If a lock exists on a path in the repository, describe it.\n"),
 
188
   {0} },
 
189
 
 
190
  {"log", subcommand_log, {0},
 
191
   N_("usage: svnlook log REPOS_PATH\n\n"
 
192
      "Print the log message.\n"),
 
193
   {'r', 't'} },
 
194
 
 
195
  {"propget", subcommand_pget, {"pget", "pg"},
 
196
   N_("usage: svnlook propget REPOS_PATH PROPNAME [PATH_IN_REPOS]\n\n"
 
197
      "Print the raw value of a property on a path in the repository.\n"
 
198
      "With --revprop, prints the raw value of a revision property.\n"),
 
199
   {'r', 't', svnlook__revprop_opt} },
 
200
 
 
201
  {"proplist", subcommand_plist, {"plist", "pl"},
 
202
   N_("usage: svnlook proplist REPOS_PATH [PATH_IN_REPOS]\n\n"
 
203
      "List the properties of a path in the repository, or\n"
 
204
      "with the --revprop option, revision properties.\n"
 
205
      "With -v, show the property values too.\n"),
 
206
   {'r', 't', 'v', svnlook__revprop_opt} },
 
207
 
 
208
  {"tree", subcommand_tree, {0},
 
209
   N_("usage: svnlook tree REPOS_PATH [PATH_IN_REPOS]\n\n"
 
210
      "Print the tree, starting at PATH_IN_REPOS (if supplied, at the root\n"
 
211
      "of the tree otherwise), optionally showing node revision ids.\n"),
 
212
   {'r', 't', svnlook__show_ids, svnlook__full_paths} },
 
213
 
 
214
  {"uuid", subcommand_uuid, {0},
 
215
   N_("usage: svnlook uuid REPOS_PATH\n\n"
 
216
      "Print the repository's UUID.\n"),
 
217
   {0} },
 
218
 
 
219
  {"youngest", subcommand_youngest, {0},
 
220
   N_("usage: svnlook youngest REPOS_PATH\n\n"
 
221
      "Print the youngest revision number.\n"),
 
222
   {0} },
 
223
 
 
224
  { NULL, NULL, {0}, NULL, {0} }
 
225
};
231
226
 
232
227
 
233
228
/* Baton for passing option/argument state to a subcommand function. */
276
271
 
277
272
/* A signal handler to support cancellation. */
278
273
static void
279
 
signal_handler (int signum)
 
274
signal_handler(int signum)
280
275
{
281
 
  apr_signal (signum, SIG_IGN);
 
276
  apr_signal(signum, SIG_IGN);
282
277
  cancelled = TRUE;
283
278
}
284
279
 
285
280
/* Our cancellation callback. */
286
281
static svn_error_t *
287
 
check_cancel (void *baton)
 
282
check_cancel(void *baton)
288
283
{
289
284
  if (cancelled)
290
 
    return svn_error_create (SVN_ERR_CANCELLED, NULL, _("Caught signal"));
 
285
    return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal"));
291
286
  else
292
287
    return SVN_NO_ERROR;
293
288
}
295
290
 
296
291
/* Version compatibility check */
297
292
static svn_error_t *
298
 
check_lib_versions (void)
 
293
check_lib_versions(void)
299
294
{
300
295
  static const svn_version_checklist_t checklist[] =
301
296
    {
307
302
      { NULL, NULL }
308
303
    };
309
304
 
310
 
  SVN_VERSION_DEFINE (my_version);
311
 
  return svn_ver_check_list (&my_version, checklist);
 
305
  SVN_VERSION_DEFINE(my_version);
 
306
  return svn_ver_check_list(&my_version, checklist);
312
307
}
313
308
 
314
309
 
316
311
   transaction specified in C, allocating in in POOL and placing it in
317
312
   *PROP_VALUE. */
318
313
static svn_error_t *
319
 
get_property (svn_string_t **prop_value,
320
 
              svnlook_ctxt_t *c, 
321
 
              const char *prop_name,
322
 
              apr_pool_t *pool)
 
314
get_property(svn_string_t **prop_value,
 
315
             svnlook_ctxt_t *c, 
 
316
             const char *prop_name,
 
317
             apr_pool_t *pool)
323
318
{
324
319
  svn_string_t *raw_value;
325
320
 
326
321
  /* Fetch transaction property... */
327
322
  if (! c->is_revision)
328
 
    SVN_ERR (svn_fs_txn_prop (&raw_value, c->txn, prop_name, pool));
 
323
    SVN_ERR(svn_fs_txn_prop(&raw_value, c->txn, prop_name, pool));
329
324
 
330
325
  /* ...or revision property -- it's your call. */
331
326
  else
332
 
    SVN_ERR (svn_fs_revision_prop (&raw_value, c->fs, c->rev_id,
333
 
                                   prop_name, pool));
 
327
    SVN_ERR(svn_fs_revision_prop(&raw_value, c->fs, c->rev_id,
 
328
                                 prop_name, pool));
334
329
 
335
330
  *prop_value = raw_value;
336
331
 
339
334
 
340
335
 
341
336
static svn_error_t *
342
 
get_root (svn_fs_root_t **root,
343
 
          svnlook_ctxt_t *c,
344
 
          apr_pool_t *pool)
 
337
get_root(svn_fs_root_t **root,
 
338
         svnlook_ctxt_t *c,
 
339
         apr_pool_t *pool)
345
340
{
346
341
  /* Open up the appropriate root (revision or transaction). */
347
342
  if (c->is_revision)
348
343
    {
349
344
      /* If we didn't get a valid revision number, we'll look at the
350
345
         youngest revision. */
351
 
      if (! SVN_IS_VALID_REVNUM (c->rev_id))
352
 
        SVN_ERR (svn_fs_youngest_rev (&(c->rev_id), c->fs, pool));
 
346
      if (! SVN_IS_VALID_REVNUM(c->rev_id))
 
347
        SVN_ERR(svn_fs_youngest_rev(&(c->rev_id), c->fs, pool));
353
348
 
354
 
      SVN_ERR (svn_fs_revision_root (root, c->fs, c->rev_id, pool));
 
349
      SVN_ERR(svn_fs_revision_root(root, c->fs, c->rev_id, pool));
355
350
    }
356
351
  else
357
352
    {
358
 
      SVN_ERR (svn_fs_txn_root (root, c->txn, pool));
 
353
      SVN_ERR(svn_fs_txn_root(root, c->txn, pool));
359
354
    }
360
355
 
361
356
  return SVN_NO_ERROR;
367
362
 
368
363
/* Generate a generic delta tree. */
369
364
static svn_error_t *
370
 
generate_delta_tree (svn_repos_node_t **tree,
371
 
                     svn_repos_t *repos,
372
 
                     svn_fs_root_t *root, 
373
 
                     svn_revnum_t base_rev, 
374
 
                     svn_boolean_t use_copy_history,
375
 
                     apr_pool_t *pool)
 
365
generate_delta_tree(svn_repos_node_t **tree,
 
366
                    svn_repos_t *repos,
 
367
                    svn_fs_root_t *root, 
 
368
                    svn_revnum_t base_rev, 
 
369
                    svn_boolean_t use_copy_history,
 
370
                    apr_pool_t *pool)
376
371
{
377
372
  svn_fs_root_t *base_root;
378
373
  const svn_delta_editor_t *editor;
379
374
  void *edit_baton;
380
 
  apr_pool_t *edit_pool = svn_pool_create (pool);
381
 
  svn_fs_t *fs = svn_repos_fs (repos);
 
375
  apr_pool_t *edit_pool = svn_pool_create(pool);
 
376
  svn_fs_t *fs = svn_repos_fs(repos);
382
377
 
383
378
  /* Get the base root. */
384
 
  SVN_ERR (svn_fs_revision_root (&base_root, fs, base_rev, pool));
 
379
  SVN_ERR(svn_fs_revision_root(&base_root, fs, base_rev, pool));
385
380
 
386
381
  /* Request our editor. */
387
 
  SVN_ERR (svn_repos_node_editor (&editor, &edit_baton, repos,
388
 
                                  base_root, root, pool, edit_pool));
 
382
  SVN_ERR(svn_repos_node_editor(&editor, &edit_baton, repos,
 
383
                                base_root, root, pool, edit_pool));
389
384
 
390
385
  /* Drive our editor. */
391
 
  SVN_ERR (svn_repos_replay (root, editor, edit_baton, edit_pool));
 
386
  SVN_ERR(svn_repos_replay2(root, "", SVN_INVALID_REVNUM, FALSE,
 
387
                            editor, edit_baton, NULL, NULL, edit_pool));
392
388
 
393
389
  /* Return the tree we just built. */
394
 
  *tree = svn_repos_node_from_baton (edit_baton);
395
 
  svn_pool_destroy (edit_pool);
 
390
  *tree = svn_repos_node_from_baton(edit_baton);
 
391
  svn_pool_destroy(edit_pool);
396
392
  return SVN_NO_ERROR;
397
393
}
398
394
 
403
399
/* Recursively print only directory nodes that either a) have property
404
400
   mods, or b) contains files that have changed. */
405
401
static svn_error_t *
406
 
print_dirs_changed_tree (svn_repos_node_t *node,
407
 
                         const char *path /* UTF-8! */,
408
 
                         apr_pool_t *pool)
 
402
print_dirs_changed_tree(svn_repos_node_t *node,
 
403
                        const char *path /* UTF-8! */,
 
404
                        apr_pool_t *pool)
409
405
{
410
406
  svn_repos_node_t *tmp_node;
411
407
  int print_me = 0;
412
408
  const char *full_path;
413
409
  apr_pool_t *subpool;
414
410
 
415
 
  SVN_ERR (check_cancel (NULL));
 
411
  SVN_ERR(check_cancel(NULL));
416
412
 
417
413
  if (! node)
418
414
    return SVN_NO_ERROR;
455
451
  /* Print the node if it qualifies. */
456
452
  if (print_me)
457
453
    {
458
 
      SVN_ERR (svn_cmdline_printf (pool, "%s/\n", path));
 
454
      SVN_ERR(svn_cmdline_printf(pool, "%s/\n", path));
459
455
    }
460
456
 
461
457
  /* Return here if the node has no children. */
464
460
    return SVN_NO_ERROR;
465
461
 
466
462
  /* Recursively handle the node's children. */
467
 
  subpool = svn_pool_create (pool);  
468
 
  full_path = svn_path_join (path, tmp_node->name, subpool);
469
 
  SVN_ERR (print_dirs_changed_tree (tmp_node, full_path, subpool));
 
463
  subpool = svn_pool_create(pool);  
 
464
  full_path = svn_path_join(path, tmp_node->name, subpool);
 
465
  SVN_ERR(print_dirs_changed_tree(tmp_node, full_path, subpool));
470
466
  while (tmp_node->sibling)
471
467
    {
472
 
      svn_pool_clear (subpool);
 
468
      svn_pool_clear(subpool);
473
469
      tmp_node = tmp_node->sibling;
474
 
      full_path = svn_path_join (path, tmp_node->name, subpool);
475
 
      SVN_ERR (print_dirs_changed_tree (tmp_node, full_path, subpool));
 
470
      full_path = svn_path_join(path, tmp_node->name, subpool);
 
471
      SVN_ERR(print_dirs_changed_tree(tmp_node, full_path, subpool));
476
472
    }
477
 
  svn_pool_destroy (subpool);
 
473
  svn_pool_destroy(subpool);
478
474
 
479
475
  return SVN_NO_ERROR;
480
476
}
483
479
/* Recursively print all nodes in the tree that have been modified
484
480
   (do not include directories affected only by "bubble-up"). */
485
481
static svn_error_t *
486
 
print_changed_tree (svn_repos_node_t *node,
487
 
                    const char *path /* UTF-8! */,
488
 
                    svn_boolean_t copy_info,
489
 
                    apr_pool_t *pool)
 
482
print_changed_tree(svn_repos_node_t *node,
 
483
                   const char *path /* UTF-8! */,
 
484
                   svn_boolean_t copy_info,
 
485
                   apr_pool_t *pool)
490
486
{
491
487
  const char *full_path;
492
488
  char status[4] = "_  ";
493
489
  int print_me = 1;
494
490
  apr_pool_t *subpool;
495
491
 
496
 
  SVN_ERR (check_cancel (NULL));
 
492
  SVN_ERR(check_cancel(NULL));
497
493
 
498
494
  if (! node)
499
495
    return SVN_NO_ERROR;
522
518
  /* Print this node unless told to skip it. */
523
519
  if (print_me)
524
520
    {
525
 
      SVN_ERR (svn_cmdline_printf (pool, "%s %s%s\n",
526
 
                                   status,
527
 
                                   path,
528
 
                                   node->kind == svn_node_dir ? "/" : ""));
 
521
      SVN_ERR(svn_cmdline_printf(pool, "%s %s%s\n",
 
522
                                 status,
 
523
                                 path,
 
524
                                 node->kind == svn_node_dir ? "/" : ""));
529
525
      if (copy_info && node->copyfrom_path)
530
526
        /* Remove the leading slash from the copyfrom path for consistency
531
527
           with the rest of the output. */
532
 
        SVN_ERR (svn_cmdline_printf (pool, "    (from %s%s:r%ld)\n",
533
 
                                     (node->copyfrom_path[0] == '/'
534
 
                                      ? node->copyfrom_path + 1
535
 
                                      : node->copyfrom_path),
536
 
                                     (node->kind == svn_node_dir ? "/" : ""),
537
 
                                     node->copyfrom_rev));
 
528
        SVN_ERR(svn_cmdline_printf(pool, "    (from %s%s:r%ld)\n",
 
529
                                   (node->copyfrom_path[0] == '/'
 
530
                                    ? node->copyfrom_path + 1
 
531
                                    : node->copyfrom_path),
 
532
                                   (node->kind == svn_node_dir ? "/" : ""),
 
533
                                   node->copyfrom_rev));
538
534
    }
539
535
  
540
536
  /* Return here if the node has no children. */
543
539
    return SVN_NO_ERROR;
544
540
 
545
541
  /* Recursively handle the node's children. */
546
 
  subpool = svn_pool_create (pool);  
547
 
  full_path = svn_path_join (path, node->name, subpool);
548
 
  SVN_ERR (print_changed_tree (node, full_path, copy_info, subpool));
 
542
  subpool = svn_pool_create(pool);  
 
543
  full_path = svn_path_join(path, node->name, subpool);
 
544
  SVN_ERR(print_changed_tree(node, full_path, copy_info, subpool));
549
545
  while (node->sibling)
550
546
    {
551
 
      svn_pool_clear (subpool);
 
547
      svn_pool_clear(subpool);
552
548
      node = node->sibling;
553
 
      full_path = svn_path_join (path, node->name, subpool);
554
 
      SVN_ERR (print_changed_tree (node, full_path, copy_info, subpool));
 
549
      full_path = svn_path_join(path, node->name, subpool);
 
550
      SVN_ERR(print_changed_tree(node, full_path, copy_info, subpool));
555
551
    }
556
 
  svn_pool_destroy (subpool);
 
552
  svn_pool_destroy(subpool);
557
553
 
558
554
  return SVN_NO_ERROR;
559
555
}
560
556
 
561
557
 
562
 
/* Set *FH to a file handle for a writable binary file at PATH.
563
 
   Create the file if it doesn't exist, truncate it if it does.
564
 
   Create ancestor directories if necessary.  Allocate *FH in POOL. */
565
 
static svn_error_t *
566
 
open_writable_binary_file (apr_file_t **fh, 
567
 
                           const char *path /* UTF-8! */, 
568
 
                           apr_pool_t *pool)
569
 
{
570
 
  apr_array_header_t *path_pieces;
571
 
  svn_error_t *err, *err2 = NULL;
572
 
  int i;
573
 
  const char *full_path, *dir;
574
 
  
575
 
  /* Try the easy way to open the file. */
576
 
  err = svn_io_file_open (fh, path, 
577
 
                          APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY,
578
 
                          APR_OS_DEFAULT, pool);
579
 
  if (! err)
580
 
    return SVN_NO_ERROR;
581
 
 
582
 
  svn_path_split (path, &dir, NULL, pool);
583
 
 
584
 
  path_pieces = svn_path_decompose (dir, pool);
585
 
 
586
 
  /* If the file path has no parent, then we've already tried to open
587
 
     it as best as we care to try above. */
588
 
  if (! path_pieces->nelts)
589
 
    return err;
590
 
 
591
 
  full_path = "";
592
 
  for (i = 0; i < path_pieces->nelts; i++)
593
 
    {
594
 
      svn_node_kind_t kind;
595
 
      const char *piece = ((const char **) (path_pieces->elts))[i];
596
 
      full_path = svn_path_join (full_path, piece, pool);
597
 
      if ((err2 = svn_io_check_resolved_path (full_path, &kind, pool)))
598
 
        goto cleanup;
599
 
 
600
 
      /* Does this path component exist at all? */
601
 
      if (kind == svn_node_none)
602
 
        {
603
 
          if ((err2 = svn_io_dir_make (full_path, APR_OS_DEFAULT, pool)))
604
 
            goto cleanup;
605
 
        }
606
 
      else if (kind != svn_node_dir)
607
 
        {
608
 
          return svn_error_createf (err->apr_err, err,
609
 
                                    _("Error creating dir '%s' (path exists)"),
610
 
                                    full_path);
611
 
        }
612
 
    }
613
 
 
614
 
  /* Now that we are ensured that the parent path for this file
615
 
     exists, try once more to open it. */
616
 
  err2 = svn_io_file_open (fh, path, 
617
 
                           APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY,
618
 
                           APR_OS_DEFAULT, pool);
619
 
 
620
 
 cleanup:
621
 
  svn_error_clear (err);
622
 
  return err2;
623
 
}
624
 
 
625
 
 
626
 
static svn_error_t *
627
 
dump_contents (apr_file_t *fh,
628
 
               svn_fs_root_t *root,
629
 
               const char *path /* UTF-8! */,
630
 
               apr_pool_t *pool)
 
558
static svn_error_t *
 
559
dump_contents(apr_file_t *fh,
 
560
              svn_fs_root_t *root,
 
561
              const char *path /* UTF-8! */,
 
562
              apr_pool_t *pool)
631
563
{
632
564
  svn_stream_t *contents, *file_stream;
633
565
 
634
566
  /* Grab the contents and copy them into fh. */
635
 
  SVN_ERR (svn_fs_file_contents (&contents, root, path, pool));
636
 
  file_stream = svn_stream_from_aprfile (fh, pool);
637
 
  SVN_ERR (svn_stream_copy (contents, file_stream, pool));
 
567
  SVN_ERR(svn_fs_file_contents(&contents, root, path, pool));
 
568
  file_stream = svn_stream_from_aprfile(fh, pool);
 
569
  SVN_ERR(svn_stream_copy(contents, file_stream, pool));
638
570
  return SVN_NO_ERROR;
639
571
}
640
572
 
652
584
 
653
585
   Use POOL for all that allocation goodness. */
654
586
static svn_error_t *
655
 
prepare_tmpfiles (const char **tmpfile1,
656
 
                  const char **tmpfile2,
657
 
                  svn_boolean_t *is_binary,
658
 
                  svn_fs_root_t *root1,
659
 
                  const char *path1,
660
 
                  svn_fs_root_t *root2,
661
 
                  const char *path2,
662
 
                  const char *tmpdir,
663
 
                  apr_pool_t *pool)
 
587
prepare_tmpfiles(const char **tmpfile1,
 
588
                 const char **tmpfile2,
 
589
                 svn_boolean_t *is_binary,
 
590
                 svn_fs_root_t *root1,
 
591
                 const char *path1,
 
592
                 svn_fs_root_t *root2,
 
593
                 const char *path2,
 
594
                 const char *tmpdir,
 
595
                 apr_pool_t *pool)
664
596
{
665
597
  svn_string_t *mimetype;
666
598
  apr_file_t *fh;
670
602
  *tmpfile2 = NULL;
671
603
  *is_binary = FALSE;
672
604
 
673
 
  assert (path1 && path2);
 
605
  assert(path1 && path2);
674
606
 
675
607
  /* Check for binary mimetypes.  If either file has a binary
676
608
     mimetype, get outta here.  */
677
609
  if (root1)
678
610
    {
679
 
      SVN_ERR (svn_fs_node_prop (&mimetype, root1, path1, 
680
 
                                 SVN_PROP_MIME_TYPE, pool));
681
 
      if (mimetype && svn_mime_type_is_binary (mimetype->data))
 
611
      SVN_ERR(svn_fs_node_prop(&mimetype, root1, path1, 
 
612
                               SVN_PROP_MIME_TYPE, pool));
 
613
      if (mimetype && svn_mime_type_is_binary(mimetype->data))
682
614
        {
683
615
          *is_binary = TRUE;
684
616
          return SVN_NO_ERROR;
686
618
    }
687
619
  if (root2)
688
620
    {
689
 
      SVN_ERR (svn_fs_node_prop (&mimetype, root2, path2, 
690
 
                                 SVN_PROP_MIME_TYPE, pool));
691
 
      if (mimetype && svn_mime_type_is_binary (mimetype->data))
 
621
      SVN_ERR(svn_fs_node_prop(&mimetype, root2, path2, 
 
622
                               SVN_PROP_MIME_TYPE, pool));
 
623
      if (mimetype && svn_mime_type_is_binary(mimetype->data))
692
624
        {
693
625
          *is_binary = TRUE;
694
626
          return SVN_NO_ERROR;
696
628
    }
697
629
 
698
630
  /* Now, prepare the two temporary files, each of which will either
699
 
     be empty, or will have real contents.  The first file we will
700
 
     make in our temporary directory. */
701
 
  *tmpfile2 = svn_path_join (tmpdir, path2, pool);
702
 
  SVN_ERR (open_writable_binary_file (&fh, *tmpfile2, pool));
 
631
     be empty, or will have real contents.  */
 
632
  SVN_ERR(svn_io_open_unique_file2(&fh, tmpfile2,
 
633
                                   apr_psprintf(pool, "%s/diff", tmpdir),
 
634
                                   ".tmp", svn_io_file_del_none, pool));
703
635
  if (root2)
704
 
    SVN_ERR (dump_contents (fh, root2, path2, pool));
705
 
  apr_file_close (fh);
 
636
    SVN_ERR(dump_contents(fh, root2, path2, pool));
 
637
  apr_file_close(fh);
706
638
 
707
639
  /* The second file is constructed from the first one's path. */
708
 
  SVN_ERR (svn_io_open_unique_file (&fh, tmpfile1, *tmpfile2, 
709
 
                                    ".tmp", FALSE, pool));
 
640
  SVN_ERR(svn_io_open_unique_file2(&fh, tmpfile1, *tmpfile2,
 
641
                                   ".tmp", svn_io_file_del_none, pool));
710
642
  if (root1)
711
 
    SVN_ERR (dump_contents (fh, root1, path1, pool));
712
 
  apr_file_close (fh);
 
643
    SVN_ERR(dump_contents(fh, root1, path1, pool));
 
644
  apr_file_close(fh);
713
645
 
714
646
  return SVN_NO_ERROR;
715
647
}
718
650
/* Generate a diff label for PATH in ROOT, allocating in POOL.
719
651
   ROOT may be NULL, in which case revision 0 is used. */
720
652
static svn_error_t *
721
 
generate_label (const char **label,
722
 
                svn_fs_root_t *root,
723
 
                const char *path,
724
 
                apr_pool_t *pool)
 
653
generate_label(const char **label,
 
654
               svn_fs_root_t *root,
 
655
               const char *path,
 
656
               apr_pool_t *pool)
725
657
{
726
658
  svn_string_t *date;
727
659
  const char *datestr;
730
662
 
731
663
  if (root)
732
664
    {
733
 
      svn_fs_t *fs = svn_fs_root_fs (root);
734
 
      if (svn_fs_is_revision_root (root))
 
665
      svn_fs_t *fs = svn_fs_root_fs(root);
 
666
      if (svn_fs_is_revision_root(root))
735
667
        {
736
 
          rev = svn_fs_revision_root_revision (root);
737
 
          SVN_ERR (svn_fs_revision_prop (&date, fs, rev, 
738
 
                                         SVN_PROP_REVISION_DATE, pool));
 
668
          rev = svn_fs_revision_root_revision(root);
 
669
          SVN_ERR(svn_fs_revision_prop(&date, fs, rev, 
 
670
                                       SVN_PROP_REVISION_DATE, pool));
739
671
        }
740
672
      else 
741
673
        {
742
674
          svn_fs_txn_t *txn;
743
 
          name = svn_fs_txn_root_name (root, pool);
744
 
          SVN_ERR (svn_fs_open_txn (&txn, fs, name, pool));
745
 
          SVN_ERR (svn_fs_txn_prop (&date, txn, SVN_PROP_REVISION_DATE, pool));
 
675
          name = svn_fs_txn_root_name(root, pool);
 
676
          SVN_ERR(svn_fs_open_txn(&txn, fs, name, pool));
 
677
          SVN_ERR(svn_fs_txn_prop(&date, txn, SVN_PROP_REVISION_DATE, pool));
746
678
        }
747
679
    }
748
680
  else
752
684
    }
753
685
  
754
686
  if (date)
755
 
    datestr = apr_psprintf (pool, "%.10s %.8s UTC", date->data, date->data + 11);
 
687
    datestr = apr_psprintf(pool, "%.10s %.8s UTC", date->data, date->data + 11);
756
688
  else
757
689
    datestr = "                       ";
758
690
 
759
691
  if (name)
760
 
    *label = apr_psprintf (pool, "%s\t%s (txn %s)", 
761
 
                           path, datestr, name); 
 
692
    *label = apr_psprintf(pool, "%s\t%s (txn %s)", 
 
693
                          path, datestr, name); 
762
694
  else
763
 
    *label = apr_psprintf (pool, "%s\t%s (rev %ld)",
764
 
                           path, datestr, rev);
 
695
    *label = apr_psprintf(pool, "%s\t%s (rev %ld)",
 
696
                          path, datestr, rev);
765
697
  return SVN_NO_ERROR;
766
698
}
767
699
 
777
709
 
778
710
/* Helper function to display differences in properties of a file */
779
711
static svn_error_t *
780
 
display_prop_diffs (const apr_array_header_t *prop_diffs,
781
 
                    apr_hash_t *orig_props,
782
 
                    const char *path,
783
 
                    apr_pool_t *pool)
 
712
display_prop_diffs(const apr_array_header_t *prop_diffs,
 
713
                   apr_hash_t *orig_props,
 
714
                   const char *path,
 
715
                   apr_pool_t *pool)
784
716
{
785
717
  int i;
786
718
 
787
 
  SVN_ERR (svn_cmdline_printf (pool, "\nProperty changes on: %s\n%s\n",
788
 
                               path, under_string));
 
719
  SVN_ERR(svn_cmdline_printf(pool, "\nProperty changes on: %s\n%s\n",
 
720
                             path, under_string));
789
721
 
790
722
  for (i = 0; i < prop_diffs->nelts; i++)
791
723
    {
792
724
      const svn_string_t *orig_value;
793
 
      const svn_prop_t *pc = &APR_ARRAY_IDX (prop_diffs, i, svn_prop_t);
 
725
      const svn_prop_t *pc = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t);
794
726
 
795
 
      SVN_ERR (check_cancel (NULL));
 
727
      SVN_ERR(check_cancel(NULL));
796
728
 
797
729
      if (orig_props)
798
 
        orig_value = apr_hash_get (orig_props, pc->name, APR_HASH_KEY_STRING);
 
730
        orig_value = apr_hash_get(orig_props, pc->name, APR_HASH_KEY_STRING);
799
731
      else
800
732
        orig_value = NULL;
801
733
 
802
 
      SVN_ERR (svn_cmdline_printf (pool, _("Name: %s\n"), pc->name));
 
734
      SVN_ERR(svn_cmdline_printf(pool, _("Name: %s\n"), pc->name));
803
735
 
804
736
      /* For now, we have a rather simple heuristic: if this is an
805
737
         "svn:" property, then assume the value is UTF-8 and must
808
740
         ### We don't use svn_cmdline_printf here, since we don't know if the
809
741
         values are UTF-8. */
810
742
      {
811
 
        svn_boolean_t val_to_utf8 = svn_prop_is_svn_prop (pc->name);
 
743
        svn_boolean_t val_to_utf8 = svn_prop_is_svn_prop(pc->name);
812
744
        const char *printable_val;
813
745
 
814
746
        if (orig_value != NULL)
815
747
          {
816
748
            if (val_to_utf8)
817
 
              SVN_ERR (svn_cmdline_cstring_from_utf8 (&printable_val, 
818
 
                                                      orig_value->data, pool));
 
749
              SVN_ERR(svn_cmdline_cstring_from_utf8(&printable_val, 
 
750
                                                    orig_value->data, pool));
819
751
            else
820
752
              printable_val = orig_value->data;
821
 
            printf ("   - %s\n", printable_val);
 
753
            printf("   - %s\n", printable_val);
822
754
          }
823
755
 
824
756
        if (pc->value != NULL)
825
757
          {
826
758
            if (val_to_utf8)
827
 
              SVN_ERR (svn_cmdline_cstring_from_utf8
828
 
                       (&printable_val, pc->value->data, pool));
 
759
              SVN_ERR(svn_cmdline_cstring_from_utf8
 
760
                      (&printable_val, pc->value->data, pool));
829
761
            else
830
762
              printable_val = pc->value->data;
831
 
            printf ("   + %s\n", printable_val);
 
763
            printf("   + %s\n", printable_val);
832
764
          }
833
765
      }
834
766
    }
835
767
 
836
 
  SVN_ERR (svn_cmdline_printf (pool, "\n"));
837
 
  return svn_cmdline_fflush (stdout);
 
768
  SVN_ERR(svn_cmdline_printf(pool, "\n"));
 
769
  return svn_cmdline_fflush(stdout);
838
770
}
839
771
 
840
772
 
842
774
/* Recursively print all nodes in the tree that have been modified
843
775
   (do not include directories affected only by "bubble-up"). */
844
776
static svn_error_t *
845
 
print_diff_tree (svn_fs_root_t *root,
846
 
                 svn_fs_root_t *base_root,
847
 
                 svn_repos_node_t *node, 
848
 
                 const char *path /* UTF-8! */,
849
 
                 const char *base_path /* UTF-8! */,
850
 
                 const svnlook_ctxt_t *c,
851
 
                 const char *tmpdir,
852
 
                 apr_pool_t *pool)
 
777
print_diff_tree(svn_fs_root_t *root,
 
778
                svn_fs_root_t *base_root,
 
779
                svn_repos_node_t *node, 
 
780
                const char *path /* UTF-8! */,
 
781
                const char *base_path /* UTF-8! */,
 
782
                const svnlook_ctxt_t *c,
 
783
                const char *tmpdir,
 
784
                apr_pool_t *pool)
853
785
{
854
786
  const char *orig_path = NULL, *new_path = NULL;
855
787
  svn_boolean_t do_diff = FALSE;
859
791
  svn_boolean_t binary = FALSE;
860
792
  apr_pool_t *subpool;
861
793
 
862
 
  SVN_ERR (check_cancel (NULL));
 
794
  SVN_ERR(check_cancel(NULL));
863
795
 
864
796
  if (! node)
865
797
    return SVN_NO_ERROR;
866
798
 
867
799
  /* Print copyfrom history for the top node of a copied tree. */
868
 
  if ((SVN_IS_VALID_REVNUM (node->copyfrom_rev))
 
800
  if ((SVN_IS_VALID_REVNUM(node->copyfrom_rev))
869
801
      && (node->copyfrom_path != NULL))
870
802
    {
871
803
      /* This is ... a copy. */
876
808
         ### Yes, it would be *much* better for something in the path
877
809
             library to be taking care of this! */
878
810
      if (node->copyfrom_path[0] == '/')
879
 
        base_path = apr_pstrdup (pool, node->copyfrom_path + 1);
 
811
        base_path = apr_pstrdup(pool, node->copyfrom_path + 1);
880
812
      else
881
 
        base_path = apr_pstrdup (pool, node->copyfrom_path);
 
813
        base_path = apr_pstrdup(pool, node->copyfrom_path);
882
814
 
883
 
      SVN_ERR (svn_cmdline_printf (pool, _("Copied: %s (from rev %ld, %s)\n"),
884
 
                                   path, node->copyfrom_rev, base_path));
 
815
      SVN_ERR(svn_cmdline_printf(pool, _("Copied: %s (from rev %ld, %s)\n"),
 
816
                                 path, node->copyfrom_rev, base_path));
885
817
 
886
818
      printed_header = TRUE;
887
819
 
888
 
      SVN_ERR (svn_fs_revision_root (&base_root,
889
 
                                     svn_fs_root_fs (base_root),
890
 
                                     node->copyfrom_rev, pool));
 
820
      SVN_ERR(svn_fs_revision_root(&base_root,
 
821
                                   svn_fs_root_fs(base_root),
 
822
                                   node->copyfrom_rev, pool));
891
823
    }
892
824
 
893
825
  /*** First, we'll just print file content diffs. ***/
901
833
           diff.
902
834
           
903
835
         - Second, dump the contents of the new version of the file
904
 
           into the svnlook temporary directory, building out the
905
 
           actual directories that need to be created in order to
906
 
           fully represent the filesystem path inside the tmp
907
 
           directory.
 
836
           into the temporary directory.
908
837
 
909
838
         - Then, dump the contents of the old version of the file into
910
 
           the svnlook temporary directory, also building out intermediate
911
 
           directories as needed, using a unique temporary file name (we
912
 
           do this *after* putting the new version of the file
913
 
           there in case something actually versioned has a name
914
 
           that looks like one of our unique identifiers).
 
839
           the temporary directory.
915
840
 
916
841
         - Next, we run 'diff', passing the repository paths as the
917
842
           labels.
918
843
 
919
 
         - Finally, we delete the temporary files (but leave the
920
 
           built-out directories in place until after all diff
921
 
           handling has been finished).  */
 
844
         - Finally, we delete the temporary files.  */
922
845
      if (node->action == 'R' && node->text_mod)
923
846
        {
924
847
          do_diff = TRUE;
925
 
          SVN_ERR (prepare_tmpfiles (&orig_path, &new_path, &binary,
926
 
                                     base_root, base_path, root, path,
927
 
                                     tmpdir, pool));
 
848
          SVN_ERR(prepare_tmpfiles(&orig_path, &new_path, &binary,
 
849
                                   base_root, base_path, root, path,
 
850
                                   tmpdir, pool));
928
851
        }
929
852
      else if (c->diff_copy_from && node->action == 'A' && is_copy)
930
853
        {
931
854
          if (node->text_mod)
932
855
            {
933
856
              do_diff = TRUE;
934
 
              SVN_ERR (prepare_tmpfiles (&orig_path, &new_path, &binary,
935
 
                                         base_root, base_path, root, path,
936
 
                                         tmpdir, pool));
 
857
              SVN_ERR(prepare_tmpfiles(&orig_path, &new_path, &binary,
 
858
                                       base_root, base_path, root, path,
 
859
                                       tmpdir, pool));
937
860
            }
938
861
        }
939
862
      else if (! c->no_diff_added && node->action == 'A')
940
863
        {
941
864
          do_diff = TRUE;
942
865
          orig_empty = TRUE;
943
 
          SVN_ERR (prepare_tmpfiles (&orig_path, &new_path, &binary,
944
 
                                     NULL, base_path, root, path,
945
 
                                     tmpdir, pool));
 
866
          SVN_ERR(prepare_tmpfiles(&orig_path, &new_path, &binary,
 
867
                                   NULL, base_path, root, path,
 
868
                                   tmpdir, pool));
946
869
        }
947
870
      else if (! c->no_diff_deleted && node->action == 'D')
948
871
        {
949
872
          do_diff = TRUE;
950
 
          SVN_ERR (prepare_tmpfiles (&orig_path, &new_path, &binary,
951
 
                                     base_root, base_path, NULL, path,
952
 
                                     tmpdir, pool));
 
873
          SVN_ERR(prepare_tmpfiles(&orig_path, &new_path, &binary,
 
874
                                   base_root, base_path, NULL, path,
 
875
                                   tmpdir, pool));
953
876
        }
954
877
 
955
878
      /* The header for the copy case has already been written, and we don't
957
880
      if (! printed_header
958
881
          && (node->action != 'R' || node->text_mod))
959
882
        {
960
 
          SVN_ERR (svn_cmdline_printf (pool, "%s: %s\n", 
961
 
                                       ((node->action == 'A') ? _("Added") :
962
 
                                        ((node->action == 'D') ? _("Deleted") :
963
 
                                         ((node->action == 'R') ? _("Modified")
964
 
                                          : _("Index")))),
965
 
                                       path));
 
883
          SVN_ERR(svn_cmdline_printf(pool, "%s: %s\n", 
 
884
                                     ((node->action == 'A') ? _("Added") :
 
885
                                      ((node->action == 'D') ? _("Deleted") :
 
886
                                       ((node->action == 'R') ? _("Modified")
 
887
                                        : _("Index")))),
 
888
                                     path));
966
889
          printed_header = TRUE;
967
890
        }
968
891
    }
969
892
 
970
893
  if (do_diff)
971
894
    {
972
 
      SVN_ERR (svn_cmdline_printf (pool, "%s\n", equal_string));
973
 
      SVN_ERR (svn_cmdline_fflush (stdout));
 
895
      SVN_ERR(svn_cmdline_printf(pool, "%s\n", equal_string));
 
896
      SVN_ERR(svn_cmdline_fflush(stdout));
974
897
 
975
898
      if (binary)
976
 
        SVN_ERR (svn_cmdline_printf (pool, _("(Binary files differ)\n")));
 
899
        SVN_ERR(svn_cmdline_printf(pool, _("(Binary files differ)\n")));
977
900
      else
978
901
        {
979
902
          svn_diff_t *diff;
980
 
          SVN_ERR (svn_diff_file_diff (&diff, orig_path, new_path, pool));
981
 
          if (svn_diff_contains_diffs (diff))
 
903
          SVN_ERR(svn_diff_file_diff(&diff, orig_path, new_path, pool));
 
904
          if (svn_diff_contains_diffs(diff))
982
905
            {
983
906
              svn_stream_t *ostream;
984
907
              const char *orig_label, *new_label;
985
908
 
986
 
              SVN_ERR (svn_stream_for_stdout (&ostream, pool));
 
909
              SVN_ERR(svn_stream_for_stdout(&ostream, pool));
987
910
              
988
911
              if (orig_empty)
989
 
                SVN_ERR (generate_label (&orig_label, NULL, path, pool));
 
912
                SVN_ERR(generate_label(&orig_label, NULL, path, pool));
990
913
              else
991
 
                SVN_ERR (generate_label (&orig_label, base_root,
992
 
                                         base_path, pool));
993
 
              SVN_ERR (generate_label (&new_label, root, path, pool));
994
 
              SVN_ERR (svn_diff_file_output_unified2
995
 
                       (ostream, diff, orig_path, new_path,
996
 
                        orig_label, new_label,
997
 
                        svn_cmdline_output_encoding (pool), pool));
998
 
              SVN_ERR (svn_stream_close (ostream));
 
914
                SVN_ERR(generate_label(&orig_label, base_root,
 
915
                                       base_path, pool));
 
916
              SVN_ERR(generate_label(&new_label, root, path, pool));
 
917
              SVN_ERR(svn_diff_file_output_unified2
 
918
                      (ostream, diff, orig_path, new_path,
 
919
                       orig_label, new_label,
 
920
                       svn_cmdline_output_encoding(pool), pool));
 
921
              SVN_ERR(svn_stream_close(ostream));
999
922
            }
1000
923
        }
1001
924
 
1002
 
      SVN_ERR (svn_cmdline_printf (pool, "\n"));
1003
 
      SVN_ERR (svn_cmdline_fflush (stdout));
 
925
      SVN_ERR(svn_cmdline_printf(pool, "\n"));
 
926
      SVN_ERR(svn_cmdline_fflush(stdout));
1004
927
    }
1005
928
  else if (printed_header)
1006
 
    SVN_ERR (svn_cmdline_printf (pool, "\n"));
 
929
    SVN_ERR(svn_cmdline_printf(pool, "\n"));
1007
930
 
1008
931
  /* Make sure we delete any temporary files. */
1009
932
  if (orig_path)
1010
 
    SVN_ERR (svn_io_remove_file (orig_path, pool));
 
933
    SVN_ERR(svn_io_remove_file(orig_path, pool));
1011
934
  if (new_path)
1012
 
    SVN_ERR (svn_io_remove_file (new_path, pool));
 
935
    SVN_ERR(svn_io_remove_file(new_path, pool));
1013
936
 
1014
937
  /*** Now handle property diffs ***/
1015
938
  if ((node->prop_mod) && (node->action != 'D'))
1018
941
      apr_hash_t *base_proptable;
1019
942
      apr_array_header_t *propchanges, *props;
1020
943
 
1021
 
      SVN_ERR (svn_fs_node_proplist (&local_proptable, root, path, pool));
 
944
      SVN_ERR(svn_fs_node_proplist(&local_proptable, root, path, pool));
1022
945
      if (node->action == 'A')
1023
 
        base_proptable = apr_hash_make (pool);
 
946
        base_proptable = apr_hash_make(pool);
1024
947
      else
1025
 
        SVN_ERR (svn_fs_node_proplist (&base_proptable, base_root, 
1026
 
                                       base_path, pool));
1027
 
      SVN_ERR (svn_prop_diffs (&propchanges, local_proptable, 
1028
 
                               base_proptable, pool));
1029
 
      SVN_ERR (svn_categorize_props (propchanges, NULL, NULL, &props, pool));
 
948
        SVN_ERR(svn_fs_node_proplist(&base_proptable, base_root, 
 
949
                                     base_path, pool));
 
950
      SVN_ERR(svn_prop_diffs(&propchanges, local_proptable, 
 
951
                             base_proptable, pool));
 
952
      SVN_ERR(svn_categorize_props(propchanges, NULL, NULL, &props, pool));
1030
953
      if (props->nelts > 0)
1031
 
        SVN_ERR (display_prop_diffs (props, base_proptable, path, pool));
 
954
        SVN_ERR(display_prop_diffs(props, base_proptable, path, pool));
1032
955
    }
1033
956
 
1034
957
  /* Return here if the node has no children. */
1037
960
    return SVN_NO_ERROR;
1038
961
 
1039
962
  /* Recursively handle the node's children. */
1040
 
  subpool = svn_pool_create (pool);
1041
 
  SVN_ERR (print_diff_tree (root, base_root, node,
1042
 
                            svn_path_join (path, node->name, subpool),
1043
 
                            svn_path_join (base_path, node->name, subpool),
1044
 
                            c, tmpdir, subpool));
 
963
  subpool = svn_pool_create(pool);
 
964
  SVN_ERR(print_diff_tree(root, base_root, node,
 
965
                          svn_path_join(path, node->name, subpool),
 
966
                          svn_path_join(base_path, node->name, subpool),
 
967
                          c, tmpdir, subpool));
1045
968
  while (node->sibling)
1046
969
    {
1047
 
      svn_pool_clear (subpool);
 
970
      svn_pool_clear(subpool);
1048
971
      node = node->sibling;
1049
 
      SVN_ERR (print_diff_tree (root, base_root, node,
1050
 
                                svn_path_join (path, node->name, subpool),
1051
 
                                svn_path_join (base_path, node->name, subpool),
1052
 
                                c, tmpdir, subpool));
 
972
      SVN_ERR(print_diff_tree(root, base_root, node,
 
973
                              svn_path_join(path, node->name, subpool),
 
974
                              svn_path_join(base_path, node->name, subpool),
 
975
                              c, tmpdir, subpool));
1053
976
    }
1054
 
  apr_pool_destroy (subpool);
 
977
  apr_pool_destroy(subpool);
1055
978
 
1056
979
  return SVN_NO_ERROR;
1057
980
}
1067
990
 
1068
991
   Use POOL for all allocations.  */
1069
992
static svn_error_t *
1070
 
print_tree (svn_fs_root_t *root,
1071
 
            const char *path /* UTF-8! */,
1072
 
            const svn_fs_id_t *id,
1073
 
            svn_boolean_t is_dir,
1074
 
            int indentation,
1075
 
            svn_boolean_t show_ids,
1076
 
            svn_boolean_t full_paths,
1077
 
            apr_pool_t *pool)
 
993
print_tree(svn_fs_root_t *root,
 
994
           const char *path /* UTF-8! */,
 
995
           const svn_fs_id_t *id,
 
996
           svn_boolean_t is_dir,
 
997
           int indentation,
 
998
           svn_boolean_t show_ids,
 
999
           svn_boolean_t full_paths,
 
1000
           apr_pool_t *pool)
1078
1001
{
1079
1002
  apr_pool_t *subpool;
1080
1003
  int i;
1081
1004
  apr_hash_t *entries;
1082
1005
  apr_hash_index_t *hi;
1083
1006
 
1084
 
  SVN_ERR (check_cancel (NULL));
 
1007
  SVN_ERR(check_cancel(NULL));
1085
1008
 
1086
1009
  /* Print the indentation. */
1087
1010
  if(!full_paths)
1088
1011
    for (i = 0; i < indentation; i++)
1089
 
      SVN_ERR (svn_cmdline_fputs (" ", stdout, pool));
 
1012
      SVN_ERR(svn_cmdline_fputs(" ", stdout, pool));
1090
1013
 
1091
1014
  /* Print the node. */
1092
 
  SVN_ERR (svn_cmdline_printf (pool, "%s%s",
1093
 
                               full_paths ? path : svn_path_basename (path,
1094
 
                                                                      pool),
1095
 
                               is_dir && strcmp (path, "/") ? "/" : ""));
 
1015
  SVN_ERR(svn_cmdline_printf(pool, "%s%s",
 
1016
                             full_paths ? path : svn_path_basename(path,
 
1017
                                                                   pool),
 
1018
                             is_dir && strcmp(path, "/") ? "/" : ""));
1096
1019
 
1097
1020
  if (show_ids)
1098
1021
    {
1099
1022
      svn_string_t *unparsed_id = NULL;
1100
1023
      if (id)
1101
 
        unparsed_id = svn_fs_unparse_id (id, pool);
1102
 
      SVN_ERR (svn_cmdline_printf (pool, " <%s>",
1103
 
                                   unparsed_id
1104
 
                                   ? unparsed_id->data
1105
 
                                   : _("unknown")));
 
1024
        unparsed_id = svn_fs_unparse_id(id, pool);
 
1025
      SVN_ERR(svn_cmdline_printf(pool, " <%s>",
 
1026
                                 unparsed_id
 
1027
                                 ? unparsed_id->data
 
1028
                                 : _("unknown")));
1106
1029
    }
1107
 
  SVN_ERR (svn_cmdline_fputs ("\n", stdout, pool));
 
1030
  SVN_ERR(svn_cmdline_fputs("\n", stdout, pool));
1108
1031
 
1109
1032
  /* Return here if PATH is not a directory. */
1110
1033
  if (! is_dir)
1111
1034
    return SVN_NO_ERROR;
1112
1035
  
1113
1036
  /* Recursively handle the node's children. */
1114
 
  SVN_ERR (svn_fs_dir_entries (&entries, root, path, pool));
1115
 
  subpool = svn_pool_create (pool);
1116
 
  for (hi = apr_hash_first (pool, entries); hi; hi = apr_hash_next (hi))
 
1037
  SVN_ERR(svn_fs_dir_entries(&entries, root, path, pool));
 
1038
  subpool = svn_pool_create(pool);
 
1039
  for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
1117
1040
    {
1118
1041
      const void *key;
1119
1042
      apr_ssize_t keylen;
1120
1043
      void *val;
1121
1044
      svn_fs_dirent_t *entry;
1122
1045
 
1123
 
      svn_pool_clear (subpool);
1124
 
      apr_hash_this (hi, &key, &keylen, &val);
 
1046
      svn_pool_clear(subpool);
 
1047
      apr_hash_this(hi, &key, &keylen, &val);
1125
1048
      entry = val;
1126
 
      SVN_ERR (print_tree (root, svn_path_join (path, entry->name, pool),
1127
 
                           entry->id, (entry->kind == svn_node_dir),
1128
 
                           indentation + 1, show_ids, full_paths, subpool));
 
1049
      SVN_ERR(print_tree(root, svn_path_join(path, entry->name, pool),
 
1050
                         entry->id, (entry->kind == svn_node_dir),
 
1051
                         indentation + 1, show_ids, full_paths, subpool));
1129
1052
    }
1130
 
  svn_pool_destroy (subpool);
 
1053
  svn_pool_destroy(subpool);
1131
1054
 
1132
1055
  return SVN_NO_ERROR;
1133
1056
}
1138
1061
 
1139
1062
/* Print the revision's log message to stdout, followed by a newline. */
1140
1063
static svn_error_t *
1141
 
do_log (svnlook_ctxt_t *c, svn_boolean_t print_size, apr_pool_t *pool)
 
1064
do_log(svnlook_ctxt_t *c, svn_boolean_t print_size, apr_pool_t *pool)
1142
1065
{
1143
1066
  svn_string_t *prop_value;
1144
1067
  const char *prop_value_eol, *prop_value_native;
1146
1069
  svn_error_t *err;
1147
1070
  apr_size_t len;
1148
1071
 
1149
 
  SVN_ERR (get_property (&prop_value, c, SVN_PROP_REVISION_LOG, pool));
 
1072
  SVN_ERR(get_property(&prop_value, c, SVN_PROP_REVISION_LOG, pool));
1150
1073
  if (! (prop_value && prop_value->data))
1151
1074
    {
1152
 
      SVN_ERR (svn_cmdline_printf (pool, "%s\n", print_size ? "0" : ""));
 
1075
      SVN_ERR(svn_cmdline_printf(pool, "%s\n", print_size ? "0" : ""));
1153
1076
      return SVN_NO_ERROR;
1154
1077
    }
1155
1078
  
1156
1079
  /* We immitate what svn_cmdline_printf does here, since we need the byte
1157
1080
     size of what we are going to print. */
1158
1081
 
1159
 
  SVN_ERR (svn_subst_translate_cstring (prop_value->data, &prop_value_eol,
1160
 
                                        APR_EOL_STR, TRUE,
1161
 
                                        NULL, FALSE, pool));
 
1082
  SVN_ERR(svn_subst_translate_cstring2(prop_value->data, &prop_value_eol,
 
1083
                                       APR_EOL_STR, TRUE,
 
1084
                                       NULL, FALSE, pool));
1162
1085
 
1163
 
  err = svn_cmdline_cstring_from_utf8 (&prop_value_native, prop_value_eol,
1164
 
                                       pool);
 
1086
  err = svn_cmdline_cstring_from_utf8(&prop_value_native, prop_value_eol,
 
1087
                                      pool);
1165
1088
  if (err)
1166
1089
    {
1167
 
      svn_error_clear (err);
1168
 
      prop_value_native = svn_cmdline_cstring_from_utf8_fuzzy (prop_value_eol,
1169
 
                                                               pool);
 
1090
      svn_error_clear(err);
 
1091
      prop_value_native = svn_cmdline_cstring_from_utf8_fuzzy(prop_value_eol,
 
1092
                                                              pool);
1170
1093
    }
1171
1094
 
1172
 
  len = strlen (prop_value_native);
 
1095
  len = strlen(prop_value_native);
1173
1096
 
1174
1097
  if (print_size)
1175
 
    SVN_ERR (svn_cmdline_printf (pool, "%" APR_SIZE_T_FMT "\n", len));
 
1098
    SVN_ERR(svn_cmdline_printf(pool, "%" APR_SIZE_T_FMT "\n", len));
1176
1099
 
1177
1100
  /* Use a stream to bypass all stdio translations. */
1178
 
  SVN_ERR (svn_cmdline_fflush (stdout));
1179
 
  SVN_ERR (svn_stream_for_stdout (&stream, pool));
1180
 
  SVN_ERR (svn_stream_write (stream, prop_value_native, &len));
1181
 
  SVN_ERR (svn_stream_close (stream));
 
1101
  SVN_ERR(svn_cmdline_fflush(stdout));
 
1102
  SVN_ERR(svn_stream_for_stdout(&stream, pool));
 
1103
  SVN_ERR(svn_stream_write(stream, prop_value_native, &len));
 
1104
  SVN_ERR(svn_stream_close(stream));
1182
1105
 
1183
 
  SVN_ERR (svn_cmdline_fputs ("\n", stdout, pool));
 
1106
  SVN_ERR(svn_cmdline_fputs("\n", stdout, pool));
1184
1107
 
1185
1108
  return SVN_NO_ERROR;
1186
1109
}
1190
1113
   empty string (in the transaction case) to stdout, followed by a
1191
1114
   newline. */
1192
1115
static svn_error_t *
1193
 
do_date (svnlook_ctxt_t *c, apr_pool_t *pool)
 
1116
do_date(svnlook_ctxt_t *c, apr_pool_t *pool)
1194
1117
{
1195
1118
  svn_string_t *prop_value;
1196
1119
 
1197
 
  SVN_ERR (get_property (&prop_value, c, SVN_PROP_REVISION_DATE, pool));
 
1120
  SVN_ERR(get_property(&prop_value, c, SVN_PROP_REVISION_DATE, pool));
1198
1121
  if (prop_value && prop_value->data)
1199
1122
    {
1200
1123
      /* Convert the date for humans. */
1201
1124
      apr_time_t aprtime;
1202
1125
      const char *time_utf8;
1203
1126
      
1204
 
      SVN_ERR (svn_time_from_cstring (&aprtime, prop_value->data, pool));
 
1127
      SVN_ERR(svn_time_from_cstring(&aprtime, prop_value->data, pool));
1205
1128
 
1206
 
      time_utf8 = svn_time_to_human_cstring (aprtime, pool);
 
1129
      time_utf8 = svn_time_to_human_cstring(aprtime, pool);
1207
1130
      
1208
 
      SVN_ERR (svn_cmdline_printf (pool, "%s", time_utf8));
 
1131
      SVN_ERR(svn_cmdline_printf(pool, "%s", time_utf8));
1209
1132
    }
1210
1133
 
1211
 
  SVN_ERR (svn_cmdline_printf (pool, "\n"));
 
1134
  SVN_ERR(svn_cmdline_printf(pool, "\n"));
1212
1135
  return SVN_NO_ERROR;
1213
1136
}
1214
1137
 
1215
1138
 
1216
1139
/* Print the author of the commit to stdout, followed by a newline. */
1217
1140
static svn_error_t *
1218
 
do_author (svnlook_ctxt_t *c, apr_pool_t *pool)
 
1141
do_author(svnlook_ctxt_t *c, apr_pool_t *pool)
1219
1142
{
1220
1143
  svn_string_t *prop_value;
1221
1144
 
1222
 
  SVN_ERR (get_property (&prop_value, c,
1223
 
                         SVN_PROP_REVISION_AUTHOR, pool));
 
1145
  SVN_ERR(get_property(&prop_value, c,
 
1146
                       SVN_PROP_REVISION_AUTHOR, pool));
1224
1147
  if (prop_value && prop_value->data) 
1225
 
    SVN_ERR (svn_cmdline_printf (pool, "%s", prop_value->data));
 
1148
    SVN_ERR(svn_cmdline_printf(pool, "%s", prop_value->data));
1226
1149
  
1227
 
  SVN_ERR (svn_cmdline_printf (pool, "\n"));
 
1150
  SVN_ERR(svn_cmdline_printf(pool, "\n"));
1228
1151
  return SVN_NO_ERROR;
1229
1152
}
1230
1153
 
1232
1155
/* Print a list of all directories in which files, or directory
1233
1156
   properties, have been modified. */
1234
1157
static svn_error_t *
1235
 
do_dirs_changed (svnlook_ctxt_t *c, apr_pool_t *pool)
 
1158
do_dirs_changed(svnlook_ctxt_t *c, apr_pool_t *pool)
1236
1159
1237
1160
  svn_fs_root_t *root;
1238
1161
  svn_revnum_t base_rev_id;
1239
1162
  svn_repos_node_t *tree;
1240
1163
 
1241
 
  SVN_ERR (get_root (&root, c, pool));
 
1164
  SVN_ERR(get_root(&root, c, pool));
1242
1165
  if (c->is_revision)
1243
1166
    base_rev_id = c->rev_id - 1;
1244
1167
  else
1245
 
    base_rev_id = svn_fs_txn_base_revision (c->txn);
 
1168
    base_rev_id = svn_fs_txn_base_revision(c->txn);
1246
1169
 
1247
 
  if (! SVN_IS_VALID_REVNUM (base_rev_id))
 
1170
  if (! SVN_IS_VALID_REVNUM(base_rev_id))
1248
1171
    return svn_error_createf 
1249
1172
      (SVN_ERR_FS_NO_SUCH_REVISION, NULL,
1250
1173
       _("Transaction '%s' is not based on a revision; how odd"),
1251
1174
       c->txn_name);
1252
1175
  
1253
 
  SVN_ERR (generate_delta_tree (&tree, c->repos, root, base_rev_id, 
1254
 
                                TRUE, pool)); 
 
1176
  SVN_ERR(generate_delta_tree(&tree, c->repos, root, base_rev_id, 
 
1177
                              TRUE, pool)); 
1255
1178
  if (tree)
1256
 
    SVN_ERR (print_dirs_changed_tree (tree, "", pool));
 
1179
    SVN_ERR(print_dirs_changed_tree(tree, "", pool));
1257
1180
 
1258
1181
  return SVN_NO_ERROR;
1259
1182
}
1265
1188
 * on whether PATH looks like a URL or not.
1266
1189
 */
1267
1190
static svn_error_t *
1268
 
verify_path (svn_node_kind_t *kind,
1269
 
             svn_fs_root_t *root,
1270
 
             const char *path,
1271
 
             apr_pool_t *pool)
 
1191
verify_path(svn_node_kind_t *kind,
 
1192
            svn_fs_root_t *root,
 
1193
            const char *path,
 
1194
            apr_pool_t *pool)
1272
1195
{
1273
 
  SVN_ERR (svn_fs_check_path (kind, root, path, pool));
 
1196
  SVN_ERR(svn_fs_check_path(kind, root, path, pool));
1274
1197
 
1275
1198
  if (*kind == svn_node_none)
1276
1199
    {
1277
 
      if (svn_path_is_url (path))  /* check for a common mistake. */
 
1200
      if (svn_path_is_url(path))  /* check for a common mistake. */
1278
1201
        return svn_error_createf
1279
1202
          (SVN_ERR_FS_NOT_FOUND, NULL,
1280
1203
           _("'%s' is a URL, probably should be a path"), path);
1291
1214
   Error with SVN_ERR_FS_NOT_FOUND if PATH does not exist, or with
1292
1215
   SVN_ERR_FS_NOT_FILE if PATH exists but is not a file. */
1293
1216
static svn_error_t *
1294
 
do_cat (svnlook_ctxt_t *c, const char *path, apr_pool_t *pool)
 
1217
do_cat(svnlook_ctxt_t *c, const char *path, apr_pool_t *pool)
1295
1218
{
1296
1219
  svn_fs_root_t *root;
1297
1220
  svn_node_kind_t kind;
1298
1221
  svn_stream_t *fstream, *stdout_stream;
1299
 
  char buf[BUFSIZ];
1300
 
  apr_size_t len = BUFSIZ;
 
1222
  char *buf = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE);
 
1223
  apr_size_t len = SVN__STREAM_CHUNK_SIZE;
1301
1224
 
1302
 
  SVN_ERR (get_root (&root, c, pool));
1303
 
  SVN_ERR (verify_path (&kind, root, path, pool));
 
1225
  SVN_ERR(get_root(&root, c, pool));
 
1226
  SVN_ERR(verify_path(&kind, root, path, pool));
1304
1227
 
1305
1228
  if (kind != svn_node_file)
1306
1229
    return svn_error_createf 
1308
1231
 
1309
1232
  /* Else. */
1310
1233
 
1311
 
  SVN_ERR (svn_fs_file_contents (&fstream, root, path, pool));
1312
 
  SVN_ERR (svn_stream_for_stdout (&stdout_stream, pool));
 
1234
  SVN_ERR(svn_fs_file_contents(&fstream, root, path, pool));
 
1235
  SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
1313
1236
  do 
1314
1237
    {
1315
 
      SVN_ERR (check_cancel (NULL));
1316
 
      SVN_ERR (svn_stream_read (fstream, buf, &len));
1317
 
      SVN_ERR (svn_stream_write (stdout_stream, buf, &len));
 
1238
      SVN_ERR(check_cancel(NULL));
 
1239
      SVN_ERR(svn_stream_read(fstream, buf, &len));
 
1240
      SVN_ERR(svn_stream_write(stdout_stream, buf, &len));
1318
1241
    } 
1319
 
  while (len == BUFSIZ);
 
1242
  while (len == SVN__STREAM_CHUNK_SIZE);
1320
1243
 
1321
1244
  return SVN_NO_ERROR;
1322
1245
}
1325
1248
/* Print a list of all paths modified in a format compatible with `svn
1326
1249
   update'. */
1327
1250
static svn_error_t *
1328
 
do_changed (svnlook_ctxt_t *c, apr_pool_t *pool)
 
1251
do_changed(svnlook_ctxt_t *c, apr_pool_t *pool)
1329
1252
{
1330
1253
  svn_fs_root_t *root;
1331
1254
  svn_revnum_t base_rev_id;
1332
1255
  svn_repos_node_t *tree;
1333
1256
 
1334
 
  SVN_ERR (get_root (&root, c, pool));
 
1257
  SVN_ERR(get_root(&root, c, pool));
1335
1258
  if (c->is_revision)
1336
1259
    base_rev_id = c->rev_id - 1;
1337
1260
  else
1338
 
    base_rev_id = svn_fs_txn_base_revision (c->txn);
 
1261
    base_rev_id = svn_fs_txn_base_revision(c->txn);
1339
1262
 
1340
 
  if (! SVN_IS_VALID_REVNUM (base_rev_id))
 
1263
  if (! SVN_IS_VALID_REVNUM(base_rev_id))
1341
1264
    return svn_error_createf 
1342
1265
      (SVN_ERR_FS_NO_SUCH_REVISION, NULL,
1343
1266
       _("Transaction '%s' is not based on a revision; how odd"),
1344
1267
       c->txn_name);
1345
1268
  
1346
 
  SVN_ERR (generate_delta_tree (&tree, c->repos, root, base_rev_id, 
1347
 
                                TRUE, pool)); 
 
1269
  SVN_ERR(generate_delta_tree(&tree, c->repos, root, base_rev_id, 
 
1270
                              TRUE, pool)); 
1348
1271
  if (tree)
1349
 
    SVN_ERR (print_changed_tree (tree, "", c->copy_info, pool));
 
1272
    SVN_ERR(print_changed_tree(tree, "", c->copy_info, pool));
1350
1273
 
1351
1274
  return SVN_NO_ERROR;
1352
1275
}
1353
1276
 
1354
 
/* Create a new temporary directory with an 'svnlook' prefix. */
1355
 
static svn_error_t *
1356
 
create_unique_tmpdir (const char **name, apr_pool_t *pool)
1357
 
{
1358
 
  const char *unique_name;
1359
 
  const char *sys_tmp_dir;
1360
 
  const char *base;
1361
 
  unsigned int i;
1362
 
 
1363
 
  SVN_ERR (svn_io_temp_dir (&sys_tmp_dir, pool));
1364
 
  base = svn_path_join (sys_tmp_dir, "svnlook", pool);
1365
 
 
1366
 
  for (i = 1; i <= 99999; i++)
1367
 
    {
1368
 
      svn_error_t *err;
1369
 
 
1370
 
      unique_name = apr_psprintf (pool, "%s.%u", base, i);
1371
 
      /* The directory has a predictable name so it is made writeable for
1372
 
         the owner only (without relying on the umask) to inhibit symlink
1373
 
         attacks on the filenames; the filenames are also, to a certain
1374
 
         extent, predictable. */
1375
 
      err = svn_io_dir_make (unique_name,
1376
 
                             APR_UREAD | APR_UWRITE | APR_UEXECUTE,
1377
 
                             pool);
1378
 
 
1379
 
      if (!err)
1380
 
        {
1381
 
          *name = unique_name;
1382
 
          return SVN_NO_ERROR;
1383
 
        }
1384
 
 
1385
 
      if (! APR_STATUS_IS_EEXIST (err->apr_err))
1386
 
        return err;
1387
 
 
1388
 
      svn_error_clear (err);
1389
 
    }
1390
 
 
1391
 
  *name = NULL;
1392
 
  return svn_error_createf (SVN_ERR_IO_UNIQUE_NAMES_EXHAUSTED,
1393
 
                            NULL, _("Can't create temporary directory"));
1394
 
}
1395
1277
 
1396
1278
/* Print some diff-y stuff in a TBD way. :-) */
1397
1279
static svn_error_t *
1398
 
do_diff (svnlook_ctxt_t *c, apr_pool_t *pool)
 
1280
do_diff(svnlook_ctxt_t *c, apr_pool_t *pool)
1399
1281
{
1400
1282
  svn_fs_root_t *root, *base_root;
1401
1283
  svn_revnum_t base_rev_id;
1402
1284
  svn_repos_node_t *tree;
1403
1285
 
1404
 
  SVN_ERR (get_root (&root, c, pool));
 
1286
  SVN_ERR(get_root(&root, c, pool));
1405
1287
  if (c->is_revision)
1406
1288
    base_rev_id = c->rev_id - 1;
1407
1289
  else
1408
 
    base_rev_id = svn_fs_txn_base_revision (c->txn);
 
1290
    base_rev_id = svn_fs_txn_base_revision(c->txn);
1409
1291
 
1410
 
  if (! SVN_IS_VALID_REVNUM (base_rev_id))
 
1292
  if (! SVN_IS_VALID_REVNUM(base_rev_id))
1411
1293
    return svn_error_createf 
1412
1294
      (SVN_ERR_FS_NO_SUCH_REVISION, NULL,
1413
1295
       _("Transaction '%s' is not based on a revision; how odd"),
1414
1296
       c->txn_name);
1415
1297
  
1416
 
  SVN_ERR (generate_delta_tree (&tree, c->repos, root, base_rev_id, 
1417
 
                                TRUE, pool)); 
 
1298
  SVN_ERR(generate_delta_tree(&tree, c->repos, root, base_rev_id, 
 
1299
                              TRUE, pool)); 
1418
1300
  if (tree)
1419
1301
    {
1420
1302
      const char *tmpdir;
1421
 
      svn_error_t *err;
1422
 
 
1423
 
      SVN_ERR (svn_fs_revision_root (&base_root, c->fs, base_rev_id, pool));
1424
 
      SVN_ERR (create_unique_tmpdir (&tmpdir, pool));
1425
 
      err = print_diff_tree (root, base_root, tree, "", "",
1426
 
                             c, tmpdir, pool);
1427
 
      if (err)
1428
 
        {
1429
 
          svn_error_clear (svn_io_remove_dir (tmpdir, pool));
1430
 
          return err;
1431
 
        }
1432
 
      SVN_ERR (svn_io_remove_dir (tmpdir, pool));
 
1303
 
 
1304
      SVN_ERR(svn_fs_revision_root(&base_root, c->fs, base_rev_id, pool));
 
1305
      SVN_ERR(svn_io_temp_dir(&tmpdir, pool));
 
1306
 
 
1307
      SVN_ERR(print_diff_tree(root, base_root, tree, "", "",
 
1308
                              c, tmpdir, pool));
1433
1309
    }
1434
1310
  return SVN_NO_ERROR;
1435
1311
}
1447
1323
   that's reported through this callback, possibly finding and
1448
1324
   displaying node-rev-ids. */
1449
1325
static svn_error_t *
1450
 
print_history (void *baton,
1451
 
               const char *path,
1452
 
               svn_revnum_t revision,
1453
 
               apr_pool_t *pool)
 
1326
print_history(void *baton,
 
1327
              const char *path,
 
1328
              svn_revnum_t revision,
 
1329
              apr_pool_t *pool)
1454
1330
{
1455
1331
  struct print_history_baton *phb = baton;
1456
1332
 
1457
 
  SVN_ERR (check_cancel (NULL));
 
1333
  SVN_ERR(check_cancel(NULL));
1458
1334
 
1459
1335
  if (phb->show_ids)
1460
1336
    {
1462
1338
      svn_fs_root_t *rev_root;
1463
1339
      svn_string_t *id_string;
1464
1340
 
1465
 
      SVN_ERR (svn_fs_revision_root (&rev_root, phb->fs, revision, pool));
1466
 
      SVN_ERR (svn_fs_node_id (&node_id, rev_root, path, pool));
1467
 
      id_string = svn_fs_unparse_id (node_id, pool);
1468
 
      SVN_ERR (svn_cmdline_printf (pool, "%8ld   %s <%s>\n", 
1469
 
                                   revision, path, id_string->data));
 
1341
      SVN_ERR(svn_fs_revision_root(&rev_root, phb->fs, revision, pool));
 
1342
      SVN_ERR(svn_fs_node_id(&node_id, rev_root, path, pool));
 
1343
      id_string = svn_fs_unparse_id(node_id, pool);
 
1344
      SVN_ERR(svn_cmdline_printf(pool, "%8ld   %s <%s>\n", 
 
1345
                                 revision, path, id_string->data));
1470
1346
    }
1471
1347
  else
1472
1348
    {
1473
 
      SVN_ERR (svn_cmdline_printf (pool, "%8ld   %s\n", revision, path));
 
1349
      SVN_ERR(svn_cmdline_printf(pool, "%8ld   %s\n", revision, path));
1474
1350
    }
1475
1351
 
1476
1352
  return SVN_NO_ERROR;
1481
1357
   revision C->rev_id.  Optionally, SHOW_IDS.  Use POOL for
1482
1358
   allocations. */
1483
1359
static svn_error_t *
1484
 
do_history (svnlook_ctxt_t *c, 
1485
 
            const char *path, 
1486
 
            svn_boolean_t show_ids,
1487
 
            apr_pool_t *pool)
 
1360
do_history(svnlook_ctxt_t *c, 
 
1361
           const char *path, 
 
1362
           svn_boolean_t show_ids,
 
1363
           apr_pool_t *pool)
1488
1364
{
1489
1365
  struct print_history_baton args;
1490
1366
 
1491
1367
  if (show_ids)
1492
1368
    {
1493
 
      SVN_ERR (svn_cmdline_printf (pool, _("REVISION   PATH <ID>\n"
1494
 
                                           "--------   ---------\n")));
 
1369
      SVN_ERR(svn_cmdline_printf(pool, _("REVISION   PATH <ID>\n"
 
1370
                                         "--------   ---------\n")));
1495
1371
    }
1496
1372
  else
1497
1373
    {
1498
 
      SVN_ERR (svn_cmdline_printf (pool, _("REVISION   PATH\n"
1499
 
                                           "--------   ----\n")));
 
1374
      SVN_ERR(svn_cmdline_printf(pool, _("REVISION   PATH\n"
 
1375
                                         "--------   ----\n")));
1500
1376
    }
1501
1377
 
1502
1378
  /* Call our history crawler.  We want the whole lifetime of the path
1504
1380
     copies. */
1505
1381
  args.fs = c->fs;
1506
1382
  args.show_ids = show_ids;
1507
 
  SVN_ERR (svn_repos_history (c->fs, path, print_history, &args,
1508
 
                              0, c->rev_id, 1, pool));
 
1383
  SVN_ERR(svn_repos_history2(c->fs, path, print_history, &args,
 
1384
                             NULL, NULL, 0, c->rev_id, 1, pool));
1509
1385
  return SVN_NO_ERROR;
1510
1386
}
1511
1387
 
1515
1391
   SVN_ERR_PROPERTY_NOT_FOUND if no such property on PATH.
1516
1392
   If PATH is NULL, operate on a revision property. */
1517
1393
static svn_error_t *
1518
 
do_pget (svnlook_ctxt_t *c,
1519
 
         const char *propname,
1520
 
         const char *path,
1521
 
         apr_pool_t *pool)
 
1394
do_pget(svnlook_ctxt_t *c,
 
1395
        const char *propname,
 
1396
        const char *path,
 
1397
        apr_pool_t *pool)
1522
1398
{
1523
1399
  svn_fs_root_t *root;
1524
1400
  svn_string_t *prop;
1526
1402
  svn_stream_t *stdout_stream;
1527
1403
  apr_size_t len;
1528
1404
  
1529
 
  SVN_ERR (get_root (&root, c, pool));
 
1405
  SVN_ERR(get_root(&root, c, pool));
1530
1406
  if (path != NULL)
1531
1407
    {
1532
 
      SVN_ERR (verify_path (&kind, root, path, pool));
1533
 
      SVN_ERR (svn_fs_node_prop (&prop, root, path, propname, pool));
 
1408
      SVN_ERR(verify_path(&kind, root, path, pool));
 
1409
      SVN_ERR(svn_fs_node_prop(&prop, root, path, propname, pool));
1534
1410
    }
1535
1411
  else
1536
 
    SVN_ERR (get_property (&prop, c, propname, pool));
 
1412
    SVN_ERR(get_property(&prop, c, propname, pool));
1537
1413
 
1538
1414
  if (prop == NULL)
1539
1415
    {
1550
1426
 
1551
1427
  /* Else. */
1552
1428
 
1553
 
  SVN_ERR (svn_stream_for_stdout (&stdout_stream, pool));
 
1429
  SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
1554
1430
  
1555
1431
  /* Unlike the command line client, we don't translate the property
1556
1432
     value or print a trailing newline here.  We just output the raw
1557
1433
     bytes of whatever's in the repository, as svnlook is more likely
1558
1434
     to be used for automated inspections. */
1559
1435
  len = prop->len;
1560
 
  SVN_ERR (svn_stream_write (stdout_stream, prop->data, &len));
 
1436
  SVN_ERR(svn_stream_write(stdout_stream, prop->data, &len));
1561
1437
 
1562
1438
  return SVN_NO_ERROR;
1563
1439
}
1569
1445
   SVN_ERR_PROPERTY_NOT_FOUND if no such property on PATH.
1570
1446
   If PATH is NULL, operate on a revision properties. */
1571
1447
static svn_error_t *
1572
 
do_plist (svnlook_ctxt_t *c,
1573
 
          const char *path,
1574
 
          svn_boolean_t verbose,
1575
 
          apr_pool_t *pool)
 
1448
do_plist(svnlook_ctxt_t *c,
 
1449
         const char *path,
 
1450
         svn_boolean_t verbose,
 
1451
         apr_pool_t *pool)
1576
1452
{
1577
1453
  svn_stream_t *stdout_stream;
1578
1454
  svn_fs_root_t *root;
1580
1456
  apr_hash_index_t *hi;
1581
1457
  svn_node_kind_t kind;
1582
1458
 
1583
 
  SVN_ERR (svn_stream_for_stdout (&stdout_stream, pool));
 
1459
  SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));
1584
1460
  if (path != NULL)
1585
1461
    {
1586
 
      SVN_ERR (get_root (&root, c, pool));
1587
 
      SVN_ERR (verify_path (&kind, root, path, pool));
1588
 
      SVN_ERR (svn_fs_node_proplist (&props, root, path, pool));
 
1462
      SVN_ERR(get_root(&root, c, pool));
 
1463
      SVN_ERR(verify_path(&kind, root, path, pool));
 
1464
      SVN_ERR(svn_fs_node_proplist(&props, root, path, pool));
1589
1465
    }
1590
1466
  else
1591
 
      SVN_ERR (svn_fs_revision_proplist (&props, c->fs, c->rev_id, pool));
 
1467
    SVN_ERR(svn_fs_revision_proplist(&props, c->fs, c->rev_id, pool));
1592
1468
 
1593
 
  for (hi = apr_hash_first (pool, props); hi; hi = apr_hash_next (hi))
 
1469
  for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
1594
1470
    {
1595
1471
      const void *key;
1596
1472
      void *val;
1597
1473
      const char *pname;
1598
1474
      svn_string_t *propval;
1599
1475
 
1600
 
      SVN_ERR (check_cancel (NULL));
 
1476
      SVN_ERR(check_cancel(NULL));
1601
1477
 
1602
 
      apr_hash_this (hi, &key, NULL, &val);
 
1478
      apr_hash_this(hi, &key, NULL, &val);
1603
1479
      pname = key;
1604
1480
      propval = val;
1605
1481
 
1609
1485
         which sends the raw bytes to stdout, untranslated. */
1610
1486
      /* We leave printf calls here, since we don't always know the encoding
1611
1487
         of the prop value. */
1612
 
      if (svn_prop_needs_translation (pname))
1613
 
        SVN_ERR (svn_subst_detranslate_string (&propval, propval, TRUE, pool));
 
1488
      if (svn_prop_needs_translation(pname))
 
1489
        SVN_ERR(svn_subst_detranslate_string(&propval, propval, TRUE, pool));
1614
1490
 
1615
1491
      if (verbose)
1616
1492
        {
1617
1493
          const char *pname_stdout;
1618
 
          SVN_ERR (svn_cmdline_cstring_from_utf8 (&pname_stdout, pname, pool));
1619
 
          printf ("  %s : %s\n", pname_stdout, propval->data);
 
1494
          SVN_ERR(svn_cmdline_cstring_from_utf8(&pname_stdout, pname, pool));
 
1495
          printf("  %s : %s\n", pname_stdout, propval->data);
1620
1496
        }
1621
1497
      else
1622
 
        printf ("  %s\n", pname);
 
1498
        printf("  %s\n", pname);
1623
1499
    }
1624
1500
  
1625
1501
  return SVN_NO_ERROR;
1628
1504
 
1629
1505
/* Print the diff between revision 0 and our root. */
1630
1506
static svn_error_t *
1631
 
do_tree (svnlook_ctxt_t *c, 
1632
 
         const char *path,
1633
 
         svn_boolean_t show_ids, 
1634
 
         svn_boolean_t full_paths, 
1635
 
         apr_pool_t *pool)
 
1507
do_tree(svnlook_ctxt_t *c, 
 
1508
        const char *path,
 
1509
        svn_boolean_t show_ids, 
 
1510
        svn_boolean_t full_paths, 
 
1511
        apr_pool_t *pool)
1636
1512
{
1637
1513
  svn_fs_root_t *root;
1638
1514
  const svn_fs_id_t *id;
1639
1515
  svn_boolean_t is_dir;
1640
1516
 
1641
 
  SVN_ERR (get_root (&root, c, pool));
1642
 
  SVN_ERR (svn_fs_node_id (&id, root, path, pool));
1643
 
  SVN_ERR (svn_fs_is_dir (&is_dir, root, path, pool));
1644
 
  SVN_ERR (print_tree (root, path, id, is_dir, 0, show_ids, full_paths, pool));
 
1517
  SVN_ERR(get_root(&root, c, pool));
 
1518
  SVN_ERR(svn_fs_node_id(&id, root, path, pool));
 
1519
  SVN_ERR(svn_fs_is_dir(&is_dir, root, path, pool));
 
1520
  SVN_ERR(print_tree(root, path, id, is_dir, 0, show_ids, full_paths, pool));
1645
1521
  return SVN_NO_ERROR;
1646
1522
}
1647
1523
 
1648
1524
 
1649
1525
/* Custom filesystem warning function. */
1650
1526
static void
1651
 
warning_func (void *baton, 
1652
 
              svn_error_t *err)
 
1527
warning_func(void *baton, 
 
1528
             svn_error_t *err)
1653
1529
{
1654
1530
  if (! err)
1655
1531
    return;
1656
 
  svn_handle_error2 (err, stderr, FALSE, "svnlook: ");
 
1532
  svn_handle_error2(err, stderr, FALSE, "svnlook: ");
1657
1533
}
1658
1534
 
1659
1535
 
1660
1536
/* Factory function for the context baton. */
1661
1537
static svn_error_t *
1662
 
get_ctxt_baton (svnlook_ctxt_t **baton_p,
1663
 
                struct svnlook_opt_state *opt_state,
1664
 
                apr_pool_t *pool)
 
1538
get_ctxt_baton(svnlook_ctxt_t **baton_p,
 
1539
               struct svnlook_opt_state *opt_state,
 
1540
               apr_pool_t *pool)
1665
1541
{
1666
 
  svnlook_ctxt_t *baton = apr_pcalloc (pool, sizeof (*baton));
 
1542
  svnlook_ctxt_t *baton = apr_pcalloc(pool, sizeof(*baton));
1667
1543
 
1668
 
  SVN_ERR (svn_repos_open (&(baton->repos), opt_state->repos_path, pool));
1669
 
  baton->fs = svn_repos_fs (baton->repos);
1670
 
  svn_fs_set_warning_func (baton->fs, warning_func, NULL);
 
1544
  SVN_ERR(svn_repos_open(&(baton->repos), opt_state->repos_path, pool));
 
1545
  baton->fs = svn_repos_fs(baton->repos);
 
1546
  svn_fs_set_warning_func(baton->fs, warning_func, NULL);
1671
1547
  baton->show_ids = opt_state->show_ids;
1672
1548
  baton->no_diff_deleted = opt_state->no_diff_deleted;
1673
1549
  baton->no_diff_added = opt_state->no_diff_added;
1676
1552
  baton->copy_info = opt_state->copy_info;
1677
1553
  baton->is_revision = opt_state->txn ? FALSE : TRUE;
1678
1554
  baton->rev_id = opt_state->rev;
1679
 
  baton->txn_name = apr_pstrdup (pool, opt_state->txn);
 
1555
  baton->txn_name = apr_pstrdup(pool, opt_state->txn);
1680
1556
  if (baton->txn_name)
1681
 
    SVN_ERR (svn_fs_open_txn (&(baton->txn), baton->fs, 
1682
 
                              baton->txn_name, pool));
 
1557
    SVN_ERR(svn_fs_open_txn(&(baton->txn), baton->fs, 
 
1558
                            baton->txn_name, pool));
1683
1559
  else if (baton->rev_id == SVN_INVALID_REVNUM)
1684
 
    SVN_ERR (svn_fs_youngest_rev (&(baton->rev_id), baton->fs, pool));
 
1560
    SVN_ERR(svn_fs_youngest_rev(&(baton->rev_id), baton->fs, pool));
1685
1561
 
1686
1562
  *baton_p = baton;
1687
1563
  return SVN_NO_ERROR;
1693
1569
 
1694
1570
/* This implements `svn_opt_subcommand_t'. */
1695
1571
static svn_error_t *
1696
 
subcommand_author (apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1572
subcommand_author(apr_getopt_t *os, void *baton, apr_pool_t *pool)
1697
1573
{
1698
1574
  struct svnlook_opt_state *opt_state = baton;
1699
1575
  svnlook_ctxt_t *c;
1700
1576
 
1701
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1702
 
  SVN_ERR (do_author (c, pool));
 
1577
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1578
  SVN_ERR(do_author(c, pool));
1703
1579
  return SVN_NO_ERROR;
1704
1580
}
1705
1581
 
1706
1582
/* This implements `svn_opt_subcommand_t'. */
1707
1583
static svn_error_t *
1708
 
subcommand_cat (apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1584
subcommand_cat(apr_getopt_t *os, void *baton, apr_pool_t *pool)
1709
1585
{
1710
1586
  struct svnlook_opt_state *opt_state = baton;
1711
1587
  svnlook_ctxt_t *c;
1715
1591
      (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
1716
1592
       _("Missing repository path argument"));
1717
1593
 
1718
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1719
 
  SVN_ERR (do_cat (c, opt_state->arg1, pool));
1720
 
  return SVN_NO_ERROR;
1721
 
}
1722
 
 
1723
 
/* This implements `svn_opt_subcommand_t'. */
1724
 
static svn_error_t *
1725
 
subcommand_changed (apr_getopt_t *os, void *baton, apr_pool_t *pool)
1726
 
{
1727
 
  struct svnlook_opt_state *opt_state = baton;
1728
 
  svnlook_ctxt_t *c;
1729
 
 
1730
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1731
 
  SVN_ERR (do_changed (c, pool));
1732
 
  return SVN_NO_ERROR;
1733
 
}
1734
 
 
1735
 
/* This implements `svn_opt_subcommand_t'. */
1736
 
static svn_error_t *
1737
 
subcommand_date (apr_getopt_t *os, void *baton, apr_pool_t *pool)
1738
 
{
1739
 
  struct svnlook_opt_state *opt_state = baton;
1740
 
  svnlook_ctxt_t *c;
1741
 
 
1742
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1743
 
  SVN_ERR (do_date (c, pool));
1744
 
  return SVN_NO_ERROR;
1745
 
}
1746
 
 
1747
 
/* This implements `svn_opt_subcommand_t'. */
1748
 
static svn_error_t *
1749
 
subcommand_diff (apr_getopt_t *os, void *baton, apr_pool_t *pool)
1750
 
{
1751
 
  struct svnlook_opt_state *opt_state = baton;
1752
 
  svnlook_ctxt_t *c;
1753
 
 
1754
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1755
 
  SVN_ERR (do_diff (c, pool));
1756
 
  return SVN_NO_ERROR;
1757
 
}
1758
 
 
1759
 
/* This implements `svn_opt_subcommand_t'. */
1760
 
static svn_error_t *
1761
 
subcommand_dirschanged (apr_getopt_t *os, void *baton, apr_pool_t *pool)
1762
 
{
1763
 
  struct svnlook_opt_state *opt_state = baton;
1764
 
  svnlook_ctxt_t *c;
1765
 
 
1766
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1767
 
  SVN_ERR (do_dirs_changed (c, pool));
1768
 
  return SVN_NO_ERROR;
1769
 
}
1770
 
 
1771
 
/* This implements `svn_opt_subcommand_t'. */
1772
 
static svn_error_t *
1773
 
subcommand_help (apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1594
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1595
  SVN_ERR(do_cat(c, opt_state->arg1, pool));
 
1596
  return SVN_NO_ERROR;
 
1597
}
 
1598
 
 
1599
/* This implements `svn_opt_subcommand_t'. */
 
1600
static svn_error_t *
 
1601
subcommand_changed(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1602
{
 
1603
  struct svnlook_opt_state *opt_state = baton;
 
1604
  svnlook_ctxt_t *c;
 
1605
 
 
1606
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1607
  SVN_ERR(do_changed(c, pool));
 
1608
  return SVN_NO_ERROR;
 
1609
}
 
1610
 
 
1611
/* This implements `svn_opt_subcommand_t'. */
 
1612
static svn_error_t *
 
1613
subcommand_date(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1614
{
 
1615
  struct svnlook_opt_state *opt_state = baton;
 
1616
  svnlook_ctxt_t *c;
 
1617
 
 
1618
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1619
  SVN_ERR(do_date(c, pool));
 
1620
  return SVN_NO_ERROR;
 
1621
}
 
1622
 
 
1623
/* This implements `svn_opt_subcommand_t'. */
 
1624
static svn_error_t *
 
1625
subcommand_diff(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1626
{
 
1627
  struct svnlook_opt_state *opt_state = baton;
 
1628
  svnlook_ctxt_t *c;
 
1629
 
 
1630
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1631
  SVN_ERR(do_diff(c, pool));
 
1632
  return SVN_NO_ERROR;
 
1633
}
 
1634
 
 
1635
/* This implements `svn_opt_subcommand_t'. */
 
1636
static svn_error_t *
 
1637
subcommand_dirschanged(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1638
{
 
1639
  struct svnlook_opt_state *opt_state = baton;
 
1640
  svnlook_ctxt_t *c;
 
1641
 
 
1642
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1643
  SVN_ERR(do_dirs_changed(c, pool));
 
1644
  return SVN_NO_ERROR;
 
1645
}
 
1646
 
 
1647
/* This implements `svn_opt_subcommand_t'. */
 
1648
static svn_error_t *
 
1649
subcommand_help(apr_getopt_t *os, void *baton, apr_pool_t *pool)
1774
1650
{
1775
1651
  struct svnlook_opt_state *opt_state = baton;
1776
1652
  const char *header =
1779
1655
      "      options will, if invoked without one of those options, act on\n"
1780
1656
      "      the repository's youngest revision.\n"
1781
1657
      "Type 'svnlook help <subcommand>' for help on a specific subcommand.\n"
 
1658
      "Type 'svnlook --version' to see the program version and FS modules.\n"
1782
1659
      "\n"
1783
1660
      "Available subcommands:\n");
1784
1661
 
1787
1664
 
1788
1665
  svn_stringbuf_t *version_footer;
1789
1666
 
1790
 
  version_footer = svn_stringbuf_create (fs_desc_start, pool);
1791
 
  SVN_ERR (svn_fs_print_modules (version_footer, pool));
 
1667
  version_footer = svn_stringbuf_create(fs_desc_start, pool);
 
1668
  SVN_ERR(svn_fs_print_modules(version_footer, pool));
1792
1669
 
1793
 
  SVN_ERR (svn_opt_print_help (os, "svnlook", 
1794
 
                               opt_state ? opt_state->version : FALSE, 
1795
 
                               FALSE, version_footer->data,
1796
 
                               header, cmd_table, options_table, NULL,
1797
 
                               pool));
 
1670
  SVN_ERR(svn_opt_print_help(os, "svnlook", 
 
1671
                             opt_state ? opt_state->version : FALSE, 
 
1672
                             FALSE, version_footer->data,
 
1673
                             header, cmd_table, options_table, NULL,
 
1674
                             pool));
1798
1675
  
1799
1676
  return SVN_NO_ERROR;
1800
1677
}
1801
1678
 
1802
1679
/* This implements `svn_opt_subcommand_t'. */
1803
1680
static svn_error_t *
1804
 
subcommand_history (apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1681
subcommand_history(apr_getopt_t *os, void *baton, apr_pool_t *pool)
1805
1682
{
1806
1683
  struct svnlook_opt_state *opt_state = baton;
1807
1684
  svnlook_ctxt_t *c;
1810
1687
  if (opt_state->arg1)
1811
1688
    path = opt_state->arg1;
1812
1689
 
1813
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1814
 
  SVN_ERR (do_history (c, path, opt_state->show_ids, pool));
 
1690
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1691
  SVN_ERR(do_history(c, path, opt_state->show_ids, pool));
1815
1692
  return SVN_NO_ERROR;
1816
1693
}
1817
1694
 
1818
1695
 
1819
1696
/* This implements `svn_opt_subcommand_t'. */
1820
1697
static svn_error_t *
1821
 
subcommand_lock (apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1698
subcommand_lock(apr_getopt_t *os, void *baton, apr_pool_t *pool)
1822
1699
{
1823
1700
  struct svnlook_opt_state *opt_state = baton;
1824
1701
  svnlook_ctxt_t *c;
1828
1705
  if (opt_state->arg1)
1829
1706
    path = opt_state->arg1;
1830
1707
  else
1831
 
    return svn_error_create (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
1832
 
                             _("Missing path argument"));
1833
 
 
1834
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1835
 
 
1836
 
  SVN_ERR (svn_fs_get_lock (&lock, c->fs, path, pool));
 
1708
    return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
 
1709
                            _("Missing path argument"));
 
1710
 
 
1711
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1712
 
 
1713
  SVN_ERR(svn_fs_get_lock(&lock, c->fs, path, pool));
1837
1714
 
1838
1715
  if (lock)
1839
1716
    {
1840
1717
      const char *cr_date, *exp_date = "";
1841
1718
      int comment_lines = 0;
1842
1719
 
1843
 
      cr_date = svn_time_to_human_cstring (lock->creation_date, pool);
 
1720
      cr_date = svn_time_to_human_cstring(lock->creation_date, pool);
1844
1721
 
1845
1722
      if (lock->expiration_date)
1846
 
        exp_date = svn_time_to_human_cstring (lock->expiration_date, pool);
 
1723
        exp_date = svn_time_to_human_cstring(lock->expiration_date, pool);
1847
1724
 
1848
1725
      if (lock->comment)
1849
 
        comment_lines = svn_cstring_count_newlines (lock->comment) + 1;
 
1726
        comment_lines = svn_cstring_count_newlines(lock->comment) + 1;
1850
1727
 
1851
 
      SVN_ERR (svn_cmdline_printf (pool, _("UUID Token: %s\n"), lock->token));
1852
 
      SVN_ERR (svn_cmdline_printf (pool, _("Owner: %s\n"), lock->owner));
1853
 
      SVN_ERR (svn_cmdline_printf (pool, _("Created: %s\n"), cr_date));
1854
 
      SVN_ERR (svn_cmdline_printf (pool, _("Expires: %s\n"), exp_date));
1855
 
      SVN_ERR (svn_cmdline_printf (pool,
1856
 
                                   (comment_lines != 1)
1857
 
                                   ? _("Comment (%i lines):\n%s\n")
1858
 
                                   : _("Comment (%i line):\n%s\n"),
1859
 
                                   comment_lines, 
1860
 
                                   lock->comment ? lock->comment : ""));
 
1728
      SVN_ERR(svn_cmdline_printf(pool, _("UUID Token: %s\n"), lock->token));
 
1729
      SVN_ERR(svn_cmdline_printf(pool, _("Owner: %s\n"), lock->owner));
 
1730
      SVN_ERR(svn_cmdline_printf(pool, _("Created: %s\n"), cr_date));
 
1731
      SVN_ERR(svn_cmdline_printf(pool, _("Expires: %s\n"), exp_date));
 
1732
      SVN_ERR(svn_cmdline_printf(pool,
 
1733
                                 (comment_lines != 1)
 
1734
                                 ? _("Comment (%i lines):\n%s\n")
 
1735
                                 : _("Comment (%i line):\n%s\n"),
 
1736
                                 comment_lines, 
 
1737
                                 lock->comment ? lock->comment : ""));
1861
1738
    }
1862
1739
 
1863
1740
  return SVN_NO_ERROR;
1866
1743
 
1867
1744
/* This implements `svn_opt_subcommand_t'. */
1868
1745
static svn_error_t *
1869
 
subcommand_info (apr_getopt_t *os, void *baton, apr_pool_t *pool)
1870
 
{
1871
 
  struct svnlook_opt_state *opt_state = baton;
1872
 
  svnlook_ctxt_t *c;
1873
 
 
1874
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1875
 
  SVN_ERR (do_author (c, pool));
1876
 
  SVN_ERR (do_date (c, pool));
1877
 
  SVN_ERR (do_log (c, TRUE, pool));
1878
 
  return SVN_NO_ERROR;
1879
 
}
1880
 
 
1881
 
/* This implements `svn_opt_subcommand_t'. */
1882
 
static svn_error_t *
1883
 
subcommand_log (apr_getopt_t *os, void *baton, apr_pool_t *pool)
1884
 
{
1885
 
  struct svnlook_opt_state *opt_state = baton;
1886
 
  svnlook_ctxt_t *c;
1887
 
 
1888
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1889
 
  SVN_ERR (do_log (c, FALSE, pool));
1890
 
  return SVN_NO_ERROR;
1891
 
}
1892
 
 
1893
 
/* This implements `svn_opt_subcommand_t'. */
1894
 
static svn_error_t *
1895
 
subcommand_pget (apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1746
subcommand_info(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1747
{
 
1748
  struct svnlook_opt_state *opt_state = baton;
 
1749
  svnlook_ctxt_t *c;
 
1750
 
 
1751
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1752
  SVN_ERR(do_author(c, pool));
 
1753
  SVN_ERR(do_date(c, pool));
 
1754
  SVN_ERR(do_log(c, TRUE, pool));
 
1755
  return SVN_NO_ERROR;
 
1756
}
 
1757
 
 
1758
/* This implements `svn_opt_subcommand_t'. */
 
1759
static svn_error_t *
 
1760
subcommand_log(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1761
{
 
1762
  struct svnlook_opt_state *opt_state = baton;
 
1763
  svnlook_ctxt_t *c;
 
1764
 
 
1765
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1766
  SVN_ERR(do_log(c, FALSE, pool));
 
1767
  return SVN_NO_ERROR;
 
1768
}
 
1769
 
 
1770
/* This implements `svn_opt_subcommand_t'. */
 
1771
static svn_error_t *
 
1772
subcommand_pget(apr_getopt_t *os, void *baton, apr_pool_t *pool)
1896
1773
{
1897
1774
  struct svnlook_opt_state *opt_state = baton;
1898
1775
  svnlook_ctxt_t *c;
1911
1788
         _("Missing propname or repository path argument"));
1912
1789
    }
1913
1790
 
1914
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1915
 
  SVN_ERR (do_pget (c, opt_state->arg1,
1916
 
                    opt_state->revprop ? NULL : opt_state->arg2, pool));
 
1791
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1792
  SVN_ERR(do_pget(c, opt_state->arg1,
 
1793
                  opt_state->revprop ? NULL : opt_state->arg2, pool));
1917
1794
  return SVN_NO_ERROR;
1918
1795
}
1919
1796
 
1920
1797
/* This implements `svn_opt_subcommand_t'. */
1921
1798
static svn_error_t *
1922
 
subcommand_plist (apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1799
subcommand_plist(apr_getopt_t *os, void *baton, apr_pool_t *pool)
1923
1800
{
1924
1801
  struct svnlook_opt_state *opt_state = baton;
1925
1802
  svnlook_ctxt_t *c;
1929
1806
      (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
1930
1807
       _("Missing repository path argument"));
1931
1808
 
1932
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1933
 
  SVN_ERR (do_plist (c, opt_state->revprop ? NULL : opt_state->arg1, 
1934
 
                     opt_state->verbose, pool));
1935
 
  return SVN_NO_ERROR;
1936
 
}
1937
 
 
1938
 
/* This implements `svn_opt_subcommand_t'. */
1939
 
static svn_error_t *
1940
 
subcommand_tree (apr_getopt_t *os, void *baton, apr_pool_t *pool)
1941
 
{
1942
 
  struct svnlook_opt_state *opt_state = baton;
1943
 
  svnlook_ctxt_t *c;
1944
 
 
1945
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1946
 
  SVN_ERR (do_tree (c, opt_state->arg1 ? opt_state->arg1 : "", 
1947
 
                    opt_state->show_ids, opt_state->full_paths, pool));
1948
 
  return SVN_NO_ERROR;
1949
 
}
1950
 
 
1951
 
/* This implements `svn_opt_subcommand_t'. */
1952
 
static svn_error_t *
1953
 
subcommand_youngest (apr_getopt_t *os, void *baton, apr_pool_t *pool)
1954
 
{
1955
 
  struct svnlook_opt_state *opt_state = baton;
1956
 
  svnlook_ctxt_t *c;
1957
 
 
1958
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1959
 
  SVN_ERR (svn_cmdline_printf (pool, "%ld\n", c->rev_id));
1960
 
  return SVN_NO_ERROR;
1961
 
}
1962
 
 
1963
 
/* This implements `svn_opt_subcommand_t'. */
1964
 
static svn_error_t *
1965
 
subcommand_uuid (apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1809
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1810
  SVN_ERR(do_plist(c, opt_state->revprop ? NULL : opt_state->arg1, 
 
1811
                   opt_state->verbose, pool));
 
1812
  return SVN_NO_ERROR;
 
1813
}
 
1814
 
 
1815
/* This implements `svn_opt_subcommand_t'. */
 
1816
static svn_error_t *
 
1817
subcommand_tree(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1818
{
 
1819
  struct svnlook_opt_state *opt_state = baton;
 
1820
  svnlook_ctxt_t *c;
 
1821
 
 
1822
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1823
  SVN_ERR(do_tree(c, opt_state->arg1 ? opt_state->arg1 : "", 
 
1824
                  opt_state->show_ids, opt_state->full_paths, pool));
 
1825
  return SVN_NO_ERROR;
 
1826
}
 
1827
 
 
1828
/* This implements `svn_opt_subcommand_t'. */
 
1829
static svn_error_t *
 
1830
subcommand_youngest(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 
1831
{
 
1832
  struct svnlook_opt_state *opt_state = baton;
 
1833
  svnlook_ctxt_t *c;
 
1834
 
 
1835
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1836
  SVN_ERR(svn_cmdline_printf(pool, "%ld\n", c->rev_id));
 
1837
  return SVN_NO_ERROR;
 
1838
}
 
1839
 
 
1840
/* This implements `svn_opt_subcommand_t'. */
 
1841
static svn_error_t *
 
1842
subcommand_uuid(apr_getopt_t *os, void *baton, apr_pool_t *pool)
1966
1843
{
1967
1844
  struct svnlook_opt_state *opt_state = baton;
1968
1845
  svnlook_ctxt_t *c;
1969
1846
  const char *uuid;
1970
1847
 
1971
 
  SVN_ERR (get_ctxt_baton (&c, opt_state, pool));
1972
 
  SVN_ERR (svn_fs_get_uuid (c->fs, &uuid, pool));
1973
 
  SVN_ERR (svn_cmdline_printf (pool, "%s\n", uuid));
 
1848
  SVN_ERR(get_ctxt_baton(&c, opt_state, pool));
 
1849
  SVN_ERR(svn_fs_get_uuid(c->fs, &uuid, pool));
 
1850
  SVN_ERR(svn_cmdline_printf(pool, "%s\n", uuid));
1974
1851
  return SVN_NO_ERROR;
1975
1852
}
1976
1853
 
1979
1856
/*** Main. ***/
1980
1857
 
1981
1858
int
1982
 
main (int argc, const char * const *argv)
 
1859
main(int argc, const char *argv[])
1983
1860
{
1984
1861
  svn_error_t *err;
1985
1862
  apr_status_t apr_err;
1994
1871
  int i;
1995
1872
 
1996
1873
  /* Initialize the app. */
1997
 
  if (svn_cmdline_init ("svnlook", stderr) != EXIT_SUCCESS)
 
1874
  if (svn_cmdline_init("svnlook", stderr) != EXIT_SUCCESS)
1998
1875
    return EXIT_FAILURE;
1999
1876
 
2000
1877
  /* Create our top-level pool.  Use a seperate mutexless allocator,
2001
1878
   * given this application is single threaded.
2002
1879
   */
2003
 
  if (apr_allocator_create (&allocator))
 
1880
  if (apr_allocator_create(&allocator))
2004
1881
    return EXIT_FAILURE;
2005
1882
 
2006
 
  apr_allocator_max_free_set (allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);
2007
 
 
2008
 
  pool = svn_pool_create_ex (NULL, allocator);
2009
 
  apr_allocator_owner_set (allocator, pool);
2010
 
 
2011
 
  received_opts = apr_array_make (pool, SVN_OPT_MAX_OPTIONS, sizeof (int));
 
1883
  apr_allocator_max_free_set(allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);
 
1884
 
 
1885
  pool = svn_pool_create_ex(NULL, allocator);
 
1886
  apr_allocator_owner_set(allocator, pool);
 
1887
 
 
1888
  received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
2012
1889
 
2013
1890
  /* Check library versions */
2014
 
  err = check_lib_versions ();
 
1891
  err = check_lib_versions();
2015
1892
  if (err)
2016
 
    return svn_cmdline_handle_exit_error (err, pool, "svnlook: ");
 
1893
    return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
2017
1894
 
2018
1895
  /* Initialize the FS library. */
2019
 
  err = svn_fs_initialize (pool);
 
1896
  err = svn_fs_initialize(pool);
2020
1897
  if (err)
2021
 
    return svn_cmdline_handle_exit_error (err, pool, "svnlook: ");
 
1898
    return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
2022
1899
 
2023
1900
  if (argc <= 1)
2024
1901
    {
2025
 
      subcommand_help (NULL, NULL, pool);
2026
 
      svn_pool_destroy (pool);
 
1902
      subcommand_help(NULL, NULL, pool);
 
1903
      svn_pool_destroy(pool);
2027
1904
      return EXIT_FAILURE;
2028
1905
    }
2029
1906
 
2030
1907
  /* Initialize opt_state. */
2031
 
  memset (&opt_state, 0, sizeof (opt_state));
 
1908
  memset(&opt_state, 0, sizeof(opt_state));
2032
1909
  opt_state.rev = SVN_INVALID_REVNUM;
2033
1910
 
2034
1911
  /* Parse options. */
2035
 
  apr_getopt_init (&os, pool, argc, argv);
 
1912
  err = svn_cmdline__getopt_init(&os, argc, argv, pool);
 
1913
  if (err)
 
1914
    return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
 
1915
 
2036
1916
  os->interleave = 1;
2037
1917
  while (1)
2038
1918
    {
2039
1919
      const char *opt_arg;
2040
1920
 
2041
1921
      /* Parse the next option. */
2042
 
      apr_err = apr_getopt_long (os, options_table, &opt_id, &opt_arg);
2043
 
      if (APR_STATUS_IS_EOF (apr_err))
 
1922
      apr_err = apr_getopt_long(os, options_table, &opt_id, &opt_arg);
 
1923
      if (APR_STATUS_IS_EOF(apr_err))
2044
1924
        break;
2045
1925
      else if (apr_err)
2046
1926
        {
2047
 
          subcommand_help (NULL, NULL, pool);
2048
 
          svn_pool_destroy (pool);
 
1927
          subcommand_help(NULL, NULL, pool);
 
1928
          svn_pool_destroy(pool);
2049
1929
          return EXIT_FAILURE;
2050
1930
        }
2051
1931
 
2052
1932
      /* Stash the option code in an array before parsing it. */
2053
 
      APR_ARRAY_PUSH (received_opts, int) = opt_id;
 
1933
      APR_ARRAY_PUSH(received_opts, int) = opt_id;
2054
1934
 
2055
1935
      switch (opt_id) 
2056
1936
        {
2057
1937
        case 'r':
2058
1938
          {
2059
1939
            char *digits_end = NULL;
2060
 
            opt_state.rev = strtol (opt_arg, &digits_end, 10);
2061
 
            if ((! SVN_IS_VALID_REVNUM (opt_state.rev))
 
1940
            opt_state.rev = strtol(opt_arg, &digits_end, 10);
 
1941
            if ((! SVN_IS_VALID_REVNUM(opt_state.rev))
2062
1942
                || (! digits_end)
2063
1943
                || *digits_end)
2064
 
              SVN_INT_ERR (svn_error_create
2065
 
                           (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
2066
 
                            _("Invalid revision number supplied")));
 
1944
              SVN_INT_ERR(svn_error_create
 
1945
                          (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
 
1946
                           _("Invalid revision number supplied")));
2067
1947
          }
2068
1948
          break;
2069
1949
 
2086
1966
 
2087
1967
        case svnlook__version:
2088
1968
          opt_state.version = TRUE;
2089
 
          opt_state.help = TRUE;
2090
1969
          break;
2091
1970
 
2092
1971
        case svnlook__show_ids:
2114
1993
          break;
2115
1994
 
2116
1995
        default:
2117
 
          subcommand_help (NULL, NULL, pool);
2118
 
          svn_pool_destroy (pool);
 
1996
          subcommand_help(NULL, NULL, pool);
 
1997
          svn_pool_destroy(pool);
2119
1998
          return EXIT_FAILURE;
2120
1999
 
2121
2000
        }
2123
2002
 
2124
2003
  /* The --transaction and --revision options may not co-exist. */
2125
2004
  if ((opt_state.rev != SVN_INVALID_REVNUM) && opt_state.txn)
2126
 
    SVN_INT_ERR (svn_error_create 
2127
 
                 (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
2128
 
                  _("The '--transaction' (-t) and '--revision' (-r) arguments "
2129
 
                    "can not co-exist")));
 
2005
    SVN_INT_ERR(svn_error_create 
 
2006
                (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
 
2007
                 _("The '--transaction' (-t) and '--revision' (-r) arguments "
 
2008
                   "can not co-exist")));
2130
2009
 
2131
2010
  /* If the user asked for help, then the rest of the arguments are
2132
2011
     the names of subcommands to get help on (if any), or else they're
2133
2012
     just typos/mistakes.  Whatever the case, the subcommand to
2134
2013
     actually run is subcommand_help(). */
2135
2014
  if (opt_state.help)
2136
 
    subcommand = svn_opt_get_canonical_subcommand (cmd_table, "help");
 
2015
    subcommand = svn_opt_get_canonical_subcommand(cmd_table, "help");
2137
2016
 
2138
2017
  /* If we're not running the `help' subcommand, then look for a
2139
2018
     subcommand in the first argument. */
2141
2020
    {
2142
2021
      if (os->ind >= os->argc)
2143
2022
        {
2144
 
          svn_error_clear
2145
 
            (svn_cmdline_fprintf (stderr, pool,
2146
 
                                  _("Subcommand argument required\n")));
2147
 
          subcommand_help (NULL, NULL, pool);
2148
 
          svn_pool_destroy (pool);
2149
 
          return EXIT_FAILURE;
 
2023
          if (opt_state.version)
 
2024
            {
 
2025
              /* Use the "help" subcommand to handle the "--version" option. */
 
2026
              static const svn_opt_subcommand_desc_t pseudo_cmd =
 
2027
                { "--version", subcommand_help, {0}, "",
 
2028
                  {svnlook__version,  /* must accept its own option */
 
2029
                  } };
 
2030
 
 
2031
              subcommand = &pseudo_cmd;
 
2032
            }
 
2033
          else
 
2034
            {
 
2035
              svn_error_clear
 
2036
                (svn_cmdline_fprintf(stderr, pool,
 
2037
                                     _("Subcommand argument required\n")));
 
2038
              subcommand_help(NULL, NULL, pool);
 
2039
              svn_pool_destroy(pool);
 
2040
              return EXIT_FAILURE;
 
2041
            }
2150
2042
        }
2151
2043
      else
2152
2044
        {
2153
2045
          const char *first_arg = os->argv[os->ind++];
2154
 
          subcommand = svn_opt_get_canonical_subcommand (cmd_table, first_arg);
 
2046
          subcommand = svn_opt_get_canonical_subcommand(cmd_table, first_arg);
2155
2047
          if (subcommand == NULL)
2156
2048
            {
2157
2049
              const char *first_arg_utf8;
2158
 
              err = svn_utf_cstring_to_utf8 (&first_arg_utf8, first_arg,
2159
 
                                             pool);
 
2050
              err = svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg,
 
2051
                                            pool);
2160
2052
              if (err)
2161
 
                return svn_cmdline_handle_exit_error (err, pool, "svnlook: ");
 
2053
                return svn_cmdline_handle_exit_error(err, pool, "svnlook: ");
2162
2054
              svn_error_clear
2163
 
                (svn_cmdline_fprintf (stderr, pool,
2164
 
                                      _("Unknown command: '%s'\n"),
2165
 
                                      first_arg_utf8));
2166
 
              subcommand_help (NULL, NULL, pool);
2167
 
              svn_pool_destroy (pool);
 
2055
                (svn_cmdline_fprintf(stderr, pool,
 
2056
                                     _("Unknown command: '%s'\n"),
 
2057
                                     first_arg_utf8));
 
2058
              subcommand_help(NULL, NULL, pool);
 
2059
              svn_pool_destroy(pool);
2168
2060
              return EXIT_FAILURE;
2169
2061
            }
2170
2062
        }
2184
2076
      /* Get the repository. */
2185
2077
      if (os->ind < os->argc)
2186
2078
        {
2187
 
          SVN_INT_ERR (svn_utf_cstring_to_utf8 (&repos_path,
2188
 
                                                os->argv[os->ind++],
2189
 
                                                pool));
2190
 
          repos_path = svn_path_internal_style (repos_path, pool);
 
2079
          SVN_INT_ERR(svn_utf_cstring_to_utf8(&repos_path,
 
2080
                                              os->argv[os->ind++],
 
2081
                                              pool));
 
2082
          repos_path = svn_path_internal_style(repos_path, pool);
2191
2083
        }
2192
2084
 
2193
2085
      if (repos_path == NULL)
2194
2086
        {
2195
2087
          svn_error_clear
2196
 
            (svn_cmdline_fprintf (stderr, pool,
2197
 
                                  _("Repository argument required\n")));
2198
 
          subcommand_help (NULL, NULL, pool);
2199
 
          svn_pool_destroy (pool);
 
2088
            (svn_cmdline_fprintf(stderr, pool,
 
2089
                                 _("Repository argument required\n")));
 
2090
          subcommand_help(NULL, NULL, pool);
 
2091
          svn_pool_destroy(pool);
2200
2092
          return EXIT_FAILURE;
2201
2093
        }
2202
 
      else if (svn_path_is_url (repos_path))
 
2094
      else if (svn_path_is_url(repos_path))
2203
2095
        {
2204
2096
          svn_error_clear
2205
 
            (svn_cmdline_fprintf (stderr, pool,
2206
 
                      _("'%s' is a URL when it should be a path\n"),
2207
 
                      repos_path));
2208
 
          svn_pool_destroy (pool);
 
2097
            (svn_cmdline_fprintf(stderr, pool,
 
2098
                                 _("'%s' is a URL when it should be a path\n"),
 
2099
                                 repos_path));
 
2100
          svn_pool_destroy(pool);
2209
2101
          return EXIT_FAILURE;
2210
2102
        }
2211
2103
 
2214
2106
      /* Get next arg (arg1), if any. */
2215
2107
      if (os->ind < os->argc)
2216
2108
        {
2217
 
          SVN_INT_ERR (svn_utf_cstring_to_utf8
2218
 
                       (&arg1, os->argv[os->ind++], pool));
2219
 
          arg1 = svn_path_internal_style (arg1, pool);
 
2109
          SVN_INT_ERR(svn_utf_cstring_to_utf8
 
2110
                      (&arg1, os->argv[os->ind++], pool));
 
2111
          arg1 = svn_path_internal_style(arg1, pool);
2220
2112
        }
2221
2113
      opt_state.arg1 = arg1;      
2222
2114
 
2223
2115
      /* Get next arg (arg2), if any. */
2224
2116
      if (os->ind < os->argc)
2225
2117
        {
2226
 
          SVN_INT_ERR (svn_utf_cstring_to_utf8
2227
 
                       (&arg2, os->argv[os->ind++], pool));
2228
 
          arg2 = svn_path_internal_style (arg2, pool);
 
2118
          SVN_INT_ERR(svn_utf_cstring_to_utf8
 
2119
                      (&arg2, os->argv[os->ind++], pool));
 
2120
          arg2 = svn_path_internal_style(arg2, pool);
2229
2121
        }
2230
2122
      opt_state.arg2 = arg2;      
2231
2123
    }
2233
2125
  /* Check that the subcommand wasn't passed any inappropriate options. */
2234
2126
  for (i = 0; i < received_opts->nelts; i++)
2235
2127
    {
2236
 
      opt_id = APR_ARRAY_IDX (received_opts, i, int);
 
2128
      opt_id = APR_ARRAY_IDX(received_opts, i, int);
2237
2129
 
2238
2130
      /* All commands implicitly accept --help, so just skip over this
2239
2131
         when we see it. Note that we don't want to include this option
2242
2134
      if (opt_id == 'h' || opt_id == '?')
2243
2135
        continue;
2244
2136
 
2245
 
      if (! svn_opt_subcommand_takes_option (subcommand, opt_id))
 
2137
      if (! svn_opt_subcommand_takes_option(subcommand, opt_id))
2246
2138
        {
2247
2139
          const char *optstr;
2248
2140
          const apr_getopt_option_t *badopt = 
2249
 
            svn_opt_get_option_from_code (opt_id, options_table);
2250
 
          svn_opt_format_option (&optstr, badopt, FALSE, pool);
2251
 
          svn_error_clear
2252
 
            (svn_cmdline_fprintf
2253
 
             (stderr, pool,
2254
 
              _("Subcommand '%s' doesn't accept option '%s'\n"
2255
 
                "Type 'svnlook help %s' for usage.\n"),
2256
 
              subcommand->name, optstr, subcommand->name));
2257
 
          svn_pool_destroy (pool);
 
2141
            svn_opt_get_option_from_code(opt_id, options_table);
 
2142
          svn_opt_format_option(&optstr, badopt, FALSE, pool);
 
2143
          if (subcommand->name[0] == '-')
 
2144
            subcommand_help(NULL, NULL, pool);
 
2145
          else
 
2146
            svn_error_clear
 
2147
              (svn_cmdline_fprintf
 
2148
               (stderr, pool,
 
2149
                _("Subcommand '%s' doesn't accept option '%s'\n"
 
2150
                  "Type 'svnlook help %s' for usage.\n"),
 
2151
                subcommand->name, optstr, subcommand->name));
 
2152
          svn_pool_destroy(pool);
2258
2153
          return EXIT_FAILURE;
2259
2154
        }
2260
2155
    }
2261
2156
 
2262
2157
  /* Set up our cancellation support. */
2263
 
  apr_signal (SIGINT, signal_handler);
 
2158
  apr_signal(SIGINT, signal_handler);
2264
2159
#ifdef SIGBREAK
2265
2160
  /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */
2266
 
  apr_signal (SIGBREAK, signal_handler);
 
2161
  apr_signal(SIGBREAK, signal_handler);
2267
2162
#endif
2268
2163
#ifdef SIGHUP
2269
 
  apr_signal (SIGHUP, signal_handler);
 
2164
  apr_signal(SIGHUP, signal_handler);
2270
2165
#endif
2271
2166
#ifdef SIGTERM
2272
 
  apr_signal (SIGTERM, signal_handler);
 
2167
  apr_signal(SIGTERM, signal_handler);
2273
2168
#endif
2274
2169
 
2275
2170
#ifdef SIGPIPE
2277
2172
  apr_signal(SIGPIPE, SIG_IGN);
2278
2173
#endif
2279
2174
 
 
2175
#ifdef SIGXFSZ
 
2176
  /* Disable SIGXFSZ generation for the platforms that have it, otherwise
 
2177
   * working with large files when compiled against an APR that doesn't have
 
2178
   * large file support will crash the program, which is uncool. */
 
2179
  apr_signal(SIGXFSZ, SIG_IGN);
 
2180
#endif
 
2181
 
2280
2182
  /* Run the subcommand. */
2281
 
  err = (*subcommand->cmd_func) (os, &opt_state, pool);
 
2183
  err = (*subcommand->cmd_func)(os, &opt_state, pool);
2282
2184
  if (err)
2283
2185
    {
2284
 
      if (err->apr_err == SVN_ERR_CL_ARG_PARSING_ERROR)
2285
 
        {
2286
 
          svn_handle_error2 (err, stderr, FALSE, "svnlook: ");
2287
 
          svn_opt_subcommand_help (subcommand->name, cmd_table,
2288
 
                                   options_table, pool);
2289
 
        }
2290
 
      else
2291
 
        svn_handle_error2 (err, stderr, FALSE, "svnlook: ");
2292
 
      svn_error_clear (err);
2293
 
      svn_pool_destroy (pool);
 
2186
      svn_handle_error2(err, stderr, FALSE, "svnlook: ");
 
2187
      svn_error_clear(err);
 
2188
      svn_pool_destroy(pool);
2294
2189
      return EXIT_FAILURE;
2295
2190
    }
2296
2191
  else
2297
2192
    {
2298
 
      svn_pool_destroy (pool);
 
2193
      svn_pool_destroy(pool);
2299
2194
      /* Ensure everything is printed on stdout, so the user sees any
2300
2195
         print errors. */
2301
 
      SVN_INT_ERR (svn_cmdline_fflush (stdout));
 
2196
      SVN_INT_ERR(svn_cmdline_fflush(stdout));
2302
2197
      return EXIT_SUCCESS;
2303
2198
    }
2304
2199
}