~svn/ubuntu/raring/subversion/ppa

« back to all changes in this revision

Viewing changes to subversion/libsvn_client/cat.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-12-05 01:26:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051205012614-qom4xfypgtsqc2xq
Tags: 1.2.3dfsg1-3ubuntu1
Merge with the final Debian release of 1.2.3dfsg1-3, bringing in
fixes to the clean target, better documentation of the libdb4.3
upgrade and build fixes to work with swig1.3_1.3.27.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * cat.c:  implementation of the 'cat' command
 
3
 *
 
4
 * ====================================================================
 
5
 * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 
6
 *
 
7
 * This software is licensed as described in the file COPYING, which
 
8
 * you should have received as part of this distribution.  The terms
 
9
 * are also available at http://subversion.tigris.org/license-1.html.
 
10
 * If newer versions of this license are posted there, you may use a
 
11
 * newer version instead, at your option.
 
12
 *
 
13
 * This software consists of voluntary contributions made by many
 
14
 * individuals.  For exact contribution history, see the revision
 
15
 * history and logs, available at http://subversion.tigris.org/.
 
16
 * ====================================================================
 
17
 */
 
18
 
 
19
/* ==================================================================== */
 
20
 
 
21
 
 
22
 
 
23
/*** Includes. ***/
 
24
 
 
25
#include "svn_client.h"
 
26
#include "svn_string.h"
 
27
#include "svn_error.h"
 
28
#include "svn_subst.h"
 
29
#include "svn_io.h"
 
30
#include "svn_time.h"
 
31
#include "svn_path.h"
 
32
#include "svn_props.h"
 
33
#include "client.h"
 
34
 
 
35
#include "svn_private_config.h"
 
36
 
 
37
 
 
38
/*** Code. ***/
 
39
 
 
40
/* Helper function to handle copying a potentially translated verison of BASE
 
41
   or WORKING revision of a file to an output stream. */
 
42
static svn_error_t *
 
43
cat_local_file (const char *path,
 
44
                svn_stream_t *output,
 
45
                svn_wc_adm_access_t *adm_access,
 
46
                const svn_opt_revision_t *revision,
 
47
                apr_pool_t *pool)
 
48
{
 
49
  const svn_wc_entry_t *entry;
 
50
  svn_subst_keywords_t kw = { 0 };
 
51
  svn_subst_eol_style_t style;
 
52
  apr_hash_t *props;
 
53
  const char *base;
 
54
  svn_string_t *eol_style, *keywords, *special;
 
55
  const char *eol = NULL;
 
56
  svn_boolean_t local_mod = FALSE;
 
57
  apr_time_t tm;
 
58
  apr_file_t *input_file;
 
59
  svn_stream_t *input;
 
60
 
 
61
  SVN_ERR (svn_wc_entry (&entry, path, adm_access, FALSE, pool));
 
62
 
 
63
  if (! entry)
 
64
    return svn_error_createf (SVN_ERR_UNVERSIONED_RESOURCE, NULL,
 
65
                              _("'%s' is not under version control "
 
66
                                "or doesn't exist"),
 
67
                              svn_path_local_style (path, pool));
 
68
 
 
69
  if (entry->kind != svn_node_file)
 
70
    return svn_error_createf(SVN_ERR_CLIENT_IS_DIRECTORY, NULL,
 
71
                             _("'%s' refers to a directory"), path);
 
72
 
 
73
  if (revision->kind != svn_opt_revision_working)
 
74
    {
 
75
      SVN_ERR (svn_wc_get_pristine_copy_path (path, &base, pool));
 
76
      SVN_ERR (svn_wc_get_prop_diffs (NULL, &props, path, adm_access, pool));
 
77
    }
 
78
  else
 
79
    {
 
80
      svn_wc_status2_t *status;
 
81
      
 
82
      base = path;
 
83
      SVN_ERR (svn_wc_prop_list (&props, path, adm_access, pool));
 
84
      SVN_ERR (svn_wc_status2 (&status, path, adm_access, pool));
 
85
      if (status->text_status != svn_wc_status_normal)
 
86
        local_mod = TRUE;
 
87
    }
 
88
 
 
89
  eol_style = apr_hash_get (props, SVN_PROP_EOL_STYLE,
 
90
                            APR_HASH_KEY_STRING);
 
91
  keywords = apr_hash_get (props, SVN_PROP_KEYWORDS,
 
92
                           APR_HASH_KEY_STRING);
 
93
  special = apr_hash_get (props, SVN_PROP_SPECIAL,
 
94
                          APR_HASH_KEY_STRING);
 
95
  
 
96
  if (eol_style)
 
97
    svn_subst_eol_style_from_value (&style, &eol, eol_style->data);
 
98
  
 
99
  if (local_mod && (! special))
 
100
    {
 
101
      /* Use the modified time from the working copy if
 
102
         the file */
 
103
      SVN_ERR (svn_io_file_affected_time (&tm, path, pool));
 
104
    }
 
105
  else
 
106
    {
 
107
      tm = entry->cmt_date;
 
108
    }
 
109
 
 
110
  if (keywords)
 
111
    {
 
112
      const char *fmt;
 
113
      const char *author;
 
114
 
 
115
      if (local_mod)
 
116
        {
 
117
          /* For locally modified files, we'll append an 'M'
 
118
             to the revision number, and set the author to
 
119
             "(local)" since we can't always determine the
 
120
             current user's username */
 
121
          fmt = "%ldM";
 
122
          author = _("(local)");
 
123
        }
 
124
      else
 
125
        {
 
126
          fmt = "%ld";
 
127
          author = entry->cmt_author;
 
128
        }
 
129
      
 
130
      SVN_ERR (svn_subst_build_keywords 
 
131
               (&kw, keywords->data, 
 
132
                apr_psprintf (pool, fmt, entry->cmt_rev),
 
133
                entry->url, tm, author, pool));
 
134
    }
 
135
 
 
136
  SVN_ERR (svn_io_file_open (&input_file, base,
 
137
                             APR_READ, APR_OS_DEFAULT, pool));
 
138
  input = svn_stream_from_aprfile (input_file, pool);
 
139
 
 
140
  SVN_ERR (svn_subst_translate_stream2 (input, output, eol, FALSE, &kw, TRUE, 
 
141
                                        pool));
 
142
 
 
143
  SVN_ERR (svn_stream_close (input));
 
144
  SVN_ERR (svn_io_file_close (input_file, pool));
 
145
 
 
146
  return SVN_NO_ERROR;
 
147
}
 
148
 
 
149
svn_error_t *
 
150
svn_client_cat2 (svn_stream_t *out,
 
151
                 const char *path_or_url,
 
152
                 const svn_opt_revision_t *peg_revision,
 
153
                 const svn_opt_revision_t *revision,
 
154
                 svn_client_ctx_t *ctx,
 
155
                 apr_pool_t *pool)
 
156
{
 
157
  svn_ra_session_t *ra_session;
 
158
  svn_revnum_t rev;
 
159
  svn_node_kind_t url_kind;
 
160
  svn_string_t *eol_style;
 
161
  svn_string_t *keywords;
 
162
  apr_hash_t *props;
 
163
  const char *url;
 
164
 
 
165
  if (! svn_path_is_url (path_or_url)
 
166
      && (peg_revision->kind == svn_opt_revision_base
 
167
          || peg_revision->kind == svn_opt_revision_committed
 
168
          || peg_revision->kind == svn_opt_revision_unspecified)
 
169
      && (revision->kind == svn_opt_revision_base
 
170
          || revision->kind == svn_opt_revision_committed
 
171
          || revision->kind == svn_opt_revision_unspecified))
 
172
    {
 
173
      svn_wc_adm_access_t *adm_access;
 
174
    
 
175
      SVN_ERR (svn_wc_adm_open3 (&adm_access, NULL,
 
176
                                 svn_path_dirname (path_or_url, pool), FALSE,
 
177
                                 0, ctx->cancel_func, ctx->cancel_baton,
 
178
                                 pool));
 
179
 
 
180
      SVN_ERR (cat_local_file (path_or_url, out, adm_access, revision, pool));
 
181
 
 
182
      SVN_ERR (svn_wc_adm_close (adm_access));
 
183
 
 
184
      return SVN_NO_ERROR;
 
185
    }
 
186
 
 
187
  /* Get an RA plugin for this filesystem object. */
 
188
  SVN_ERR (svn_client__ra_session_from_path (&ra_session, &rev,
 
189
                                             &url, path_or_url, peg_revision,
 
190
                                             revision, ctx, pool));
 
191
 
 
192
  /* Make sure the object isn't a directory. */
 
193
  SVN_ERR (svn_ra_check_path (ra_session, "", rev, &url_kind, pool));
 
194
  if (url_kind == svn_node_dir)
 
195
    return svn_error_createf(SVN_ERR_CLIENT_IS_DIRECTORY, NULL,
 
196
                             _("URL '%s' refers to a directory"), url);
 
197
 
 
198
  /* Grab some properties we need to know in order to figure out if anything 
 
199
     special needs to be done with this file. */
 
200
  SVN_ERR (svn_ra_get_file (ra_session, "", rev, NULL, NULL, &props, pool));
 
201
 
 
202
  eol_style = apr_hash_get (props, SVN_PROP_EOL_STYLE, APR_HASH_KEY_STRING);
 
203
  keywords = apr_hash_get (props, SVN_PROP_KEYWORDS, APR_HASH_KEY_STRING);
 
204
 
 
205
  if (! eol_style && ! keywords)
 
206
    {
 
207
      /* It's a file with no special eol style or keywords. */
 
208
      SVN_ERR (svn_ra_get_file (ra_session, "", rev, out, NULL, NULL, pool));
 
209
    }
 
210
  else
 
211
    {
 
212
      svn_subst_keywords_t kw = { 0 };
 
213
      svn_subst_eol_style_t style;
 
214
      const char *temp_dir;
 
215
      const char *tmp_filename;
 
216
      svn_stream_t *tmp_stream;
 
217
      apr_file_t *tmp_file;
 
218
      apr_status_t apr_err;
 
219
      apr_off_t off = 0;
 
220
      const char *eol = NULL;
 
221
 
 
222
      /* grab a temporary file to write the target to. */
 
223
      SVN_ERR (svn_io_temp_dir (&temp_dir, pool));
 
224
      SVN_ERR (svn_io_open_unique_file (&tmp_file, &tmp_filename,
 
225
                 svn_path_join (temp_dir, "tmp", pool), ".tmp",
 
226
                 TRUE, pool));
 
227
 
 
228
      tmp_stream = svn_stream_from_aprfile (tmp_file, pool);
 
229
 
 
230
      SVN_ERR (svn_ra_get_file (ra_session, "", rev, tmp_stream, 
 
231
                                NULL, NULL, pool));
 
232
 
 
233
      /* rewind our stream. */
 
234
      apr_err = apr_file_seek (tmp_file, APR_SET, &off);
 
235
      if (apr_err)
 
236
        return svn_error_wrap_apr (apr_err, _("Can't seek in '%s'"),
 
237
                                   svn_path_local_style (tmp_filename, pool));
 
238
 
 
239
      if (eol_style)
 
240
        svn_subst_eol_style_from_value (&style, &eol, eol_style->data);
 
241
 
 
242
      if (keywords)
 
243
        {
 
244
          svn_string_t *cmt_rev, *cmt_date, *cmt_author;
 
245
          apr_time_t when = 0;
 
246
 
 
247
          cmt_rev = apr_hash_get (props, SVN_PROP_ENTRY_COMMITTED_REV,
 
248
                                  APR_HASH_KEY_STRING);
 
249
          cmt_date = apr_hash_get (props, SVN_PROP_ENTRY_COMMITTED_DATE,
 
250
                                   APR_HASH_KEY_STRING);
 
251
          cmt_author = apr_hash_get (props, SVN_PROP_ENTRY_LAST_AUTHOR,
 
252
                                     APR_HASH_KEY_STRING);
 
253
          if (cmt_date)
 
254
            SVN_ERR (svn_time_from_cstring (&when, cmt_date->data, pool));
 
255
 
 
256
          SVN_ERR (svn_subst_build_keywords
 
257
                   (&kw, keywords->data, 
 
258
                    cmt_rev->data,
 
259
                    url,
 
260
                    when,
 
261
                    cmt_author ? cmt_author->data : NULL,
 
262
                    pool));
 
263
        }
 
264
 
 
265
      SVN_ERR (svn_subst_translate_stream2 (tmp_stream, out, eol, FALSE, &kw,
 
266
                                            TRUE, pool));
 
267
 
 
268
      SVN_ERR (svn_stream_close (tmp_stream));
 
269
    }
 
270
 
 
271
  return SVN_NO_ERROR;
 
272
}
 
273
 
 
274
svn_error_t *
 
275
svn_client_cat (svn_stream_t *out,
 
276
                const char *path_or_url,
 
277
                const svn_opt_revision_t *revision,
 
278
                svn_client_ctx_t *ctx,
 
279
                apr_pool_t *pool)
 
280
{
 
281
  return svn_client_cat2 (out, path_or_url, revision, revision,
 
282
                          ctx, pool);
 
283
}