~svn/ubuntu/oneiric/subversion/ppa

« back to all changes in this revision

Viewing changes to subversion/libsvn_wc/questions.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
 * questions.c:  routines for asking questions about working copies
3
3
 *
4
4
 * ====================================================================
5
 
 * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
 
5
 * Copyright (c) 2000-2004, 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
36
36
#include "adm_files.h"
37
37
#include "questions.h"
38
38
#include "entries.h"
 
39
#include "translate.h"
39
40
 
40
41
#include "svn_md5.h"
41
42
#include <apr_md5.h>
47
48
   code.  See also adm_files.c:check_adm_exists(), which should
48
49
   probably be merged with this.  */
49
50
svn_error_t *
50
 
svn_wc_check_wc (const char *path,
51
 
                 int *wc_format,
52
 
                 apr_pool_t *pool)
 
51
svn_wc_check_wc(const char *path,
 
52
                int *wc_format,
 
53
                apr_pool_t *pool)
53
54
{
54
55
  svn_error_t *err = SVN_NO_ERROR;
55
 
  svn_node_kind_t kind;
56
 
 
57
 
  SVN_ERR (svn_io_check_path (path, &kind, pool));
58
 
  
59
 
  if (kind == svn_node_none)
60
 
    {
61
 
      return svn_error_createf
62
 
        (APR_ENOENT, NULL, _("'%s' does not exist"),
63
 
         svn_path_local_style (path, pool));
 
56
 
 
57
  const char *format_file_path
 
58
    = svn_wc__adm_path(path, FALSE, pool, SVN_WC__ADM_ENTRIES, NULL);
 
59
 
 
60
  /* First try to read the format number from the entries file. */
 
61
  err = svn_io_read_version_file(wc_format, format_file_path, pool);
 
62
 
 
63
  /* If that didn't work and the first line of the entries file contains
 
64
     something other than a number, then it is probably in XML format. */
 
65
  if (err && err->apr_err == SVN_ERR_BAD_VERSION_FILE_FORMAT)
 
66
    {
 
67
      svn_error_clear(err);
 
68
      /* Fall back on reading the format file instead.
 
69
         Note that the format file might not exist in newer working copies
 
70
         (format 7 and higher), but in that case, the entries file should
 
71
         have contained the format number. */
 
72
      format_file_path
 
73
        = svn_wc__adm_path(path, FALSE, pool, SVN_WC__ADM_FORMAT, NULL);
 
74
 
 
75
      err = svn_io_read_version_file(wc_format, format_file_path, pool);
 
76
    }      
 
77
 
 
78
  if (err && (APR_STATUS_IS_ENOENT(err->apr_err)
 
79
              || APR_STATUS_IS_ENOTDIR(err->apr_err)))
 
80
    {
 
81
      svn_node_kind_t kind;
 
82
 
 
83
      svn_error_clear(err);
 
84
 
 
85
      /* Check path itself exists. */
 
86
      SVN_ERR(svn_io_check_path(path, &kind, pool));
 
87
 
 
88
      if (kind == svn_node_none)
 
89
        {
 
90
          return svn_error_createf
 
91
            (APR_ENOENT, NULL, _("'%s' does not exist"),
 
92
            svn_path_local_style(path, pool));
 
93
        }
 
94
 
 
95
      /* If the format file does not exist or path not directory, then for
 
96
         our purposes this is not a working copy, so return 0. */
 
97
      *wc_format = 0;
64
98
    }
65
 
  else if (kind != svn_node_dir)
66
 
    *wc_format = 0;
67
 
  else  /* okay, it's a directory, but is it a working copy? */
 
99
  else if (err)
 
100
    return err;
 
101
  else
68
102
    {
69
 
      const char *format_file_path
70
 
        = svn_wc__adm_path (path, FALSE, pool, SVN_WC__ADM_FORMAT, NULL);
71
 
 
72
 
      err = svn_io_read_version_file (wc_format, format_file_path, pool);
73
 
 
74
 
      if (err && (APR_STATUS_IS_ENOENT(err->apr_err)
75
 
                  || APR_STATUS_IS_ENOTDIR(err->apr_err)))
76
 
        {
77
 
          /* If the format file does not exist, then for our purposes
78
 
             this is not a working copy, so return 0. */
79
 
          svn_error_clear (err);
80
 
          *wc_format = 0;
81
 
        }
82
 
      else if (err)
83
 
        return err;
84
 
      else
85
 
        {
86
 
          /* If we managed to read the format file we assume that we
87
 
             are dealing with a real wc so we can return a nice
88
 
             error. */
89
 
          SVN_ERR (svn_wc__check_format (*wc_format, path, pool));
90
 
        }
 
103
      /* If we managed to read the format file we assume that we
 
104
          are dealing with a real wc so we can return a nice
 
105
          error. */
 
106
      SVN_ERR(svn_wc__check_format(*wc_format, path, pool));
91
107
    }
92
108
 
93
109
  return SVN_NO_ERROR;
95
111
 
96
112
 
97
113
svn_error_t *
98
 
svn_wc__check_format (int wc_format, const char *path, apr_pool_t *pool)
 
114
svn_wc__check_format(int wc_format, const char *path, apr_pool_t *pool)
99
115
{
100
116
  if (wc_format < 2)
101
117
    {
103
119
        (SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
104
120
         _("Working copy format of '%s' is too old (%d); "
105
121
           "please check out your working copy again"),
106
 
         svn_path_local_style (path, pool), wc_format);
 
122
         svn_path_local_style(path, pool), wc_format);
107
123
    }
108
124
  else if (wc_format > SVN_WC__VERSION)
109
125
    {
111
127
        (SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,
112
128
         _("This client is too old to work with working copy '%s'; "
113
129
           "please get a newer Subversion client"),
114
 
         svn_path_local_style (path, pool));
 
130
         svn_path_local_style(path, pool));
115
131
    }
116
132
 
117
133
  return SVN_NO_ERROR;
126
142
   "Are the contents of F different than the contents of
127
143
   .svn/text-base/F.svn-base?"
128
144
 
129
 
   or
130
 
 
131
 
   "Are the contents of .svn/props/xxx different than
132
 
   .svn/prop-base/xxx.svn-base?"
133
 
 
134
145
   In other words, we're looking to see if a user has made local
135
146
   modifications to a file since the last update or commit.
136
147
 
152
163
   `entries' file?  Return the answer in EQUAL_P.  TIMESTAMP_KIND
153
164
   should be one of the enumerated type above. */
154
165
svn_error_t *
155
 
svn_wc__timestamps_equal_p (svn_boolean_t *equal_p,
156
 
                            const char *path,
157
 
                            svn_wc_adm_access_t *adm_access,
158
 
                            enum svn_wc__timestamp_kind timestamp_kind,
159
 
                            apr_pool_t *pool)
 
166
svn_wc__timestamps_equal_p(svn_boolean_t *equal_p,
 
167
                           const char *path,
 
168
                           svn_wc_adm_access_t *adm_access,
 
169
                           enum svn_wc__timestamp_kind timestamp_kind,
 
170
                           apr_pool_t *pool)
160
171
{
161
172
  apr_time_t wfile_time, entrytime = 0;
162
173
  const svn_wc_entry_t *entry;
163
174
 
164
175
  /* Get the timestamp from the entries file */
165
 
  SVN_ERR (svn_wc_entry (&entry, path, adm_access, FALSE, pool));
 
176
  SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool));
166
177
 
167
178
  /* Can't compare timestamps for an unversioned file. */
168
179
  if (entry == NULL)
169
180
    return svn_error_createf
170
181
      (SVN_ERR_ENTRY_NOT_FOUND, NULL,
171
182
       _("'%s' is not under version control"),
172
 
       svn_path_local_style (path, pool));
 
183
       svn_path_local_style(path, pool));
173
184
 
174
185
  /* Get the timestamp from the working file and the entry */
175
186
  if (timestamp_kind == svn_wc__text_time)
176
187
    {
177
 
      SVN_ERR (svn_io_file_affected_time (&wfile_time, path, pool));
 
188
      SVN_ERR(svn_io_file_affected_time(&wfile_time, path, pool));
178
189
      entrytime = entry->text_time;
179
190
    }
180
191
  
182
193
    {
183
194
      const char *prop_path;
184
195
 
185
 
      SVN_ERR (svn_wc__prop_path (&prop_path, path, adm_access, FALSE, pool));
186
 
      SVN_ERR (svn_io_file_affected_time (&wfile_time, prop_path, pool));
 
196
      SVN_ERR(svn_wc__prop_path(&prop_path, path, entry->kind, FALSE, pool));
 
197
      SVN_ERR(svn_io_file_affected_time(&wfile_time, prop_path, pool));
187
198
      entrytime = entry->prop_time;
188
199
    }
189
200
 
219
230
}
220
231
 
221
232
 
222
 
 
223
 
 
224
 
svn_error_t *
225
 
svn_wc__versioned_file_modcheck (svn_boolean_t *modified_p,
226
 
                                 const char *versioned_file,
227
 
                                 svn_wc_adm_access_t *adm_access,
228
 
                                 const char *base_file,
229
 
                                 apr_pool_t *pool)
230
 
{
231
 
  svn_boolean_t same;
232
 
  const char *tmp_vfile;
233
 
  svn_error_t *err = SVN_NO_ERROR, *err2 = SVN_NO_ERROR;
234
 
 
235
 
  SVN_ERR (svn_wc_translated_file (&tmp_vfile, versioned_file, adm_access,
236
 
                                   TRUE, pool));
237
 
  
238
 
  err = svn_io_files_contents_same_p (&same, tmp_vfile, base_file, pool);
239
 
  *modified_p = (! same);
240
 
  
241
 
  if (tmp_vfile != versioned_file)
242
 
    err2 = svn_io_remove_file (tmp_vfile, pool);
243
 
 
244
 
  if (err)
245
 
    {
246
 
      if (err2)
247
 
        svn_error_compose (err, err2);
248
 
      return err;
249
 
    }
250
 
 
251
 
  return err2;
252
 
}
253
 
 
254
 
 
255
 
/* Set *MODIFIED_P to true if (after translation) VERSIONED_FILE
256
 
 * differs from BASE_FILE, else to false if not.  Also, verify that
257
 
 * BASE_FILE matches the entry checksum for VERSIONED_FILE; if it
258
 
 * does not match, return the error SVN_ERR_WC_CORRUPT_TEXT_BASE.
 
233
/* Set *MODIFIED_P to TRUE if (after translation) VERSIONED_FILE
 
234
 * differs from BASE_FILE, else to FALSE if not.  Also verify that
 
235
 * BASE_FILE matches the entry checksum for VERSIONED_FILE, if
 
236
 * verify_checksum is TRUE. If checksum does not match, return the error
 
237
 * SVN_ERR_WC_CORRUPT_TEXT_BASE.
259
238
 *
260
239
 * ADM_ACCESS is an access baton for VERSIONED_FILE.  Use POOL for
261
240
 * temporary allocation.
262
241
 */
263
242
static svn_error_t *
264
 
compare_and_verify (svn_boolean_t *modified_p,
265
 
                    const char *versioned_file,
266
 
                    svn_wc_adm_access_t *adm_access,
267
 
                    const char *base_file,
268
 
                    apr_pool_t *pool)
269
 
 
 
243
compare_and_verify(svn_boolean_t *modified_p,
 
244
                   const char *versioned_file,
 
245
                   svn_wc_adm_access_t *adm_access,
 
246
                   const char *base_file,
 
247
                   svn_boolean_t compare_textbases,
 
248
                   svn_boolean_t verify_checksum,
 
249
                   apr_pool_t *pool)
270
250
{
271
 
  const char *tmp_vfile;
272
 
  svn_error_t *err = SVN_NO_ERROR, *err2 = SVN_NO_ERROR;
273
 
  const svn_wc_entry_t *entry;
274
 
 
275
 
  SVN_ERR (svn_wc_entry (&entry, versioned_file, adm_access, TRUE, pool));
276
 
 
277
 
 
278
 
  SVN_ERR (svn_wc_translated_file (&tmp_vfile, versioned_file, adm_access,
279
 
                                   TRUE, pool));
280
 
 
281
 
  /* Compare the files, while maybe calculating the base file's checksum. */
282
 
  {
283
 
    /* "v_" means versioned_file, "b_" means base_file. */
284
 
    svn_error_t *v_err = SVN_NO_ERROR;
285
 
    svn_error_t *b_err = SVN_NO_ERROR;
286
 
    apr_size_t v_file_bytes_read, b_file_bytes_read;
287
 
    char v_buf[BUFSIZ], b_buf[BUFSIZ];
288
 
    apr_file_t *v_file_h = NULL;
289
 
    apr_file_t *b_file_h = NULL;
290
 
    apr_pool_t *loop_pool;
291
 
 
292
 
    int identical = TRUE;
293
 
    unsigned char digest[APR_MD5_DIGESTSIZE];
294
 
    apr_md5_ctx_t context;
295
 
 
296
 
    SVN_ERR (svn_io_file_open (&v_file_h, tmp_vfile,
297
 
                               APR_READ, APR_OS_DEFAULT, pool));
298
 
    SVN_ERR (svn_io_file_open (&b_file_h, base_file, APR_READ, APR_OS_DEFAULT,
 
251
  svn_boolean_t same;
 
252
  svn_subst_eol_style_t eol_style;
 
253
  const char *eol_str;
 
254
  apr_hash_t *keywords;
 
255
  svn_boolean_t special;
 
256
  svn_boolean_t need_translation;
 
257
 
 
258
 
 
259
  SVN_ERR(svn_wc__get_eol_style(&eol_style, &eol_str, versioned_file,
 
260
                                adm_access, pool));
 
261
  SVN_ERR(svn_wc__get_keywords(&keywords, versioned_file,
 
262
                              adm_access, NULL, pool));
 
263
  SVN_ERR(svn_wc__get_special(&special, versioned_file, adm_access, pool));
 
264
 
 
265
 
 
266
  need_translation = svn_subst_translation_required(eol_style, eol_str,
 
267
                                                    keywords, special, TRUE);
 
268
  if (verify_checksum || need_translation)
 
269
    {
 
270
      /* Reading files is necessary. */
 
271
      const unsigned char *digest;
 
272
      /* "v_" means versioned_file, "b_" means base_file. */
 
273
      apr_file_t *v_file_h, *b_file_h;
 
274
      svn_stream_t *v_stream, *b_stream;
 
275
      const svn_wc_entry_t *entry;
 
276
      
 
277
      SVN_ERR(svn_io_file_open(&b_file_h, base_file, APR_READ,
 
278
                              APR_OS_DEFAULT, pool));
 
279
 
 
280
      b_stream = svn_stream_from_aprfile2(b_file_h, FALSE, pool);
 
281
 
 
282
      if (verify_checksum)
 
283
        {
 
284
          /* Need checksum verification, so read checksum from entries file
 
285
           * and setup checksummed stream for base file. */
 
286
          SVN_ERR(svn_wc_entry(&entry, versioned_file, adm_access, TRUE,
299
287
                               pool));
300
 
    if (entry->checksum)
301
 
      apr_md5_init (&context);
302
 
 
303
 
    loop_pool = svn_pool_create (pool);
304
 
    do
305
 
      {
306
 
        svn_pool_clear (loop_pool);
307
 
 
308
 
        /* The only way v_err can be true here is if we hit EOF. */
309
 
        if (! v_err)
310
 
          {
311
 
            v_err = svn_io_file_read_full (v_file_h, v_buf, sizeof(v_buf),
312
 
                                           &v_file_bytes_read, loop_pool);
313
 
            if (v_err && !APR_STATUS_IS_EOF(v_err->apr_err))
314
 
              return v_err;
315
 
          }
316
 
        
317
 
        b_err = svn_io_file_read_full (b_file_h, b_buf, sizeof(b_buf),
318
 
                                       &b_file_bytes_read, loop_pool);
319
 
        if (b_err && !APR_STATUS_IS_EOF(b_err->apr_err))
320
 
          return b_err;
321
 
        
322
 
        if (entry->checksum)
323
 
          apr_md5_update (&context, b_buf, b_file_bytes_read);
324
 
 
325
 
        if ((v_err && (! b_err))
326
 
            || (v_file_bytes_read != b_file_bytes_read)
327
 
            || (memcmp (v_buf, b_buf, v_file_bytes_read)))
328
 
          {
329
 
            identical = FALSE;
330
 
          }
331
 
      } while (! b_err);
332
 
    
333
 
    svn_pool_destroy (loop_pool);
334
 
 
335
 
    /* Clear any errors, but don't set the error variables to null, as
336
 
       we still depend on them for conditionals. */
337
 
    svn_error_clear (v_err);
338
 
    svn_error_clear (b_err);
339
 
    
340
 
    SVN_ERR (svn_io_file_close (v_file_h, pool));
341
 
    SVN_ERR (svn_io_file_close (b_file_h, pool));
342
 
 
343
 
    if (entry->checksum)
344
 
      {
345
 
        const char *checksum;
346
 
        apr_md5_final (digest, &context);
347
 
        checksum = svn_md5_digest_to_cstring_display (digest, pool);
348
 
        if (strcmp (checksum, entry->checksum) != 0)
349
 
          {
 
288
          if (! entry)
350
289
            return svn_error_createf
351
 
              (SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
352
 
               _("Checksum mismatch indicates corrupt text base: '%s'\n"
353
 
                 "   expected:  %s\n"
354
 
                 "     actual:  %s\n"),
355
 
               svn_path_local_style (base_file, pool),
356
 
               entry->checksum,
357
 
               checksum);
358
 
          }
359
 
      }
360
 
 
361
 
    *modified_p = ! identical;
362
 
  }
363
 
  
364
 
  if (tmp_vfile != versioned_file)
365
 
    err2 = svn_io_remove_file (tmp_vfile, pool);
366
 
 
367
 
  if (err)
 
290
              (SVN_ERR_UNVERSIONED_RESOURCE, NULL,
 
291
                _("'%s' is not under version control"),
 
292
                svn_path_local_style(versioned_file, pool));
 
293
 
 
294
          if (entry->checksum)
 
295
            b_stream = svn_stream_checksummed(b_stream, &digest, NULL, TRUE,
 
296
                                              pool);
 
297
        }
 
298
 
 
299
      if (compare_textbases && need_translation)
 
300
        {
 
301
          /* Create stream for detranslate versioned file to normal form. */
 
302
          SVN_ERR(svn_subst_stream_detranslated(&v_stream,
 
303
                                                versioned_file,
 
304
                                                eol_style,
 
305
                                                eol_str, TRUE,
 
306
                                                keywords, special,
 
307
                                                pool));
 
308
        }
 
309
      else
 
310
        {
 
311
          SVN_ERR(svn_io_file_open(&v_file_h, versioned_file, APR_READ,
 
312
                              APR_OS_DEFAULT, pool));
 
313
          v_stream = svn_stream_from_aprfile2(v_file_h, FALSE, pool);
 
314
 
 
315
          if (need_translation)
 
316
            {
 
317
              /* Translate text-base to working copy form. */
 
318
              b_stream = svn_subst_stream_translated(b_stream, eol_str,
 
319
                                                     FALSE, keywords, TRUE,
 
320
                                                     pool);
 
321
            }
 
322
        }
 
323
 
 
324
      SVN_ERR(svn_stream_contents_same(&same, b_stream, v_stream, pool));
 
325
      
 
326
      SVN_ERR(svn_stream_close(v_stream));
 
327
      SVN_ERR(svn_stream_close(b_stream));
 
328
 
 
329
      if (verify_checksum && entry->checksum)
 
330
        {
 
331
          const char *checksum;
 
332
          checksum = svn_md5_digest_to_cstring_display(digest, pool);
 
333
          if (strcmp(checksum, entry->checksum) != 0)
 
334
            {
 
335
              return svn_error_createf
 
336
                (SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
 
337
                  _("Checksum mismatch indicates corrupt text base: '%s'\n"
 
338
                    "   expected:  %s\n"
 
339
                    "     actual:  %s\n"),
 
340
                  svn_path_local_style(base_file, pool),
 
341
                  entry->checksum,
 
342
                  checksum);
 
343
            }
 
344
        }
 
345
    }
 
346
  else
368
347
    {
369
 
      if (err2)
370
 
        svn_error_compose (err, err2);
371
 
      return err;
 
348
      /* Translation would be a no-op, so compare the original file. */
 
349
      SVN_ERR(svn_io_files_contents_same_p(&same, base_file, versioned_file,
 
350
                                           pool));
372
351
    }
373
352
 
374
 
  return err2;
375
 
}
376
 
 
377
 
 
378
 
svn_error_t *
379
 
svn_wc_text_modified_p (svn_boolean_t *modified_p,
380
 
                        const char *filename,
381
 
                        svn_boolean_t force_comparison,
382
 
                        svn_wc_adm_access_t *adm_access,
383
 
                        apr_pool_t *pool)
 
353
 
 
354
 
 
355
  *modified_p = (! same);
 
356
  return SVN_NO_ERROR;
 
357
}
 
358
 
 
359
svn_error_t *
 
360
svn_wc__versioned_file_modcheck(svn_boolean_t *modified_p,
 
361
                                const char *versioned_file,
 
362
                                svn_wc_adm_access_t *adm_access,
 
363
                                const char *base_file,
 
364
                                svn_boolean_t compare_textbases,
 
365
                                apr_pool_t *pool)
 
366
{
 
367
  return compare_and_verify(modified_p, versioned_file, adm_access,
 
368
                            base_file, compare_textbases, FALSE, pool);
 
369
}
 
370
 
 
371
svn_error_t *
 
372
svn_wc__text_modified_internal_p(svn_boolean_t *modified_p,
 
373
                                 const char *filename,
 
374
                                 svn_boolean_t force_comparison,
 
375
                                 svn_wc_adm_access_t *adm_access,
 
376
                                 svn_boolean_t compare_textbases,
 
377
                                 apr_pool_t *pool)
384
378
{
385
379
  const char *textbase_filename;
386
380
  svn_boolean_t equal_timestamps;
387
 
  apr_pool_t *subpool = svn_pool_create (pool);
 
381
  apr_pool_t *subpool = svn_pool_create(pool);
388
382
  svn_node_kind_t kind;
389
383
  svn_error_t *err;
390
384
 
395
389
         theoretically, be wrong in certain rare cases, but with the
396
390
         addition of a forced delay after commits (see revision 419
397
391
         and issue #542) it's highly unlikely to be a problem. */
398
 
      err = svn_wc__timestamps_equal_p (&equal_timestamps,
399
 
                                        filename, adm_access,
400
 
                                        svn_wc__text_time, subpool);
 
392
      err = svn_wc__timestamps_equal_p(&equal_timestamps,
 
393
                                       filename, adm_access,
 
394
                                       svn_wc__text_time, subpool);
401
395
 
402
396
      /* We only care whether there was an error or not, so make sure it
403
397
         is cleared. */
404
 
      svn_error_clear (err);
 
398
      svn_error_clear(err);
405
399
 
406
400
      /* If we have an error, we fall back on the slower code path below.
407
401
         It might be tempting to optimize this further, for example by
417
411
    }
418
412
 
419
413
  /* Make sure the file exists before proceeding. */
420
 
  SVN_ERR (svn_io_check_path (filename, &kind, pool));
 
414
  SVN_ERR(svn_io_check_path(filename, &kind, pool));
421
415
  if (kind != svn_node_file)
422
416
    {
423
417
      /* If the file doesn't exist, consider it non-modified. */
428
422
  /* If there's no text-base file, we have to assume the working file
429
423
     is modified.  For example, a file scheduled for addition but not
430
424
     yet committed. */
431
 
  textbase_filename = svn_wc__text_base_path (filename, 0, subpool);
432
 
  SVN_ERR (svn_io_check_path (textbase_filename, &kind, subpool));
 
425
  textbase_filename = svn_wc__text_base_path(filename, 0, subpool);
 
426
  SVN_ERR(svn_io_check_path(textbase_filename, &kind, subpool));
433
427
  if (kind != svn_node_file)
434
428
    {
435
429
      *modified_p = TRUE;
436
430
      goto cleanup;
437
431
    }
438
 
  
439
 
  
440
 
  if (force_comparison)  /* Check all bytes, and verify checksum. */
441
 
    {
442
 
      SVN_ERR (compare_and_verify (modified_p,
443
 
                                   filename,
444
 
                                   adm_access,
445
 
                                   textbase_filename,
446
 
                                   subpool));
447
 
    }
448
 
  else  /* Else, fall back on the standard mod detector. */
449
 
    {
450
 
      SVN_ERR (svn_wc__versioned_file_modcheck (modified_p,
451
 
                                                filename,
452
 
                                                adm_access,
453
 
                                                textbase_filename,
454
 
                                                subpool));
455
 
    }
 
432
 
 
433
 
 
434
  /* Check all bytes, and verify checksum if requested. */
 
435
  SVN_ERR(compare_and_verify(modified_p,
 
436
                             filename,
 
437
                             adm_access,
 
438
                             textbase_filename,
 
439
                             compare_textbases,
 
440
                             force_comparison,
 
441
                             subpool));
456
442
 
457
443
  /* It is quite legitimate for modifications to the working copy to
458
444
     produce a timestamp variation with no text variation. If it turns out
459
445
     that there are no differences then we might be able to "repair" the
460
446
     text-time in the entries file and so avoid the expensive file contents
461
447
     comparison in the future. */
462
 
  if (! *modified_p && svn_wc_adm_locked (adm_access))
 
448
  if (! *modified_p && svn_wc_adm_locked(adm_access))
463
449
    {
464
450
      svn_wc_entry_t tmp;
465
 
      SVN_ERR (svn_io_file_affected_time (&tmp.text_time, filename, pool));
466
 
      SVN_ERR (svn_wc__entry_modify (adm_access,
467
 
                                     svn_path_basename (filename, pool),
468
 
                                     &tmp, SVN_WC__ENTRY_MODIFY_TEXT_TIME, TRUE,
469
 
                                     pool));
 
451
      SVN_ERR(svn_io_file_affected_time(&tmp.text_time, filename, pool));
 
452
      SVN_ERR(svn_wc__entry_modify(adm_access,
 
453
                                   svn_path_basename(filename, pool),
 
454
                                   &tmp, SVN_WC__ENTRY_MODIFY_TEXT_TIME, TRUE,
 
455
                                   pool));
470
456
    }
471
457
 
472
458
 cleanup:
473
 
  svn_pool_destroy (subpool);
 
459
  svn_pool_destroy(subpool);
474
460
 
475
461
  return SVN_NO_ERROR;
476
462
}
477
463
 
478
464
 
 
465
svn_error_t *
 
466
svn_wc_text_modified_p(svn_boolean_t *modified_p,
 
467
                       const char *filename,
 
468
                       svn_boolean_t force_comparison,
 
469
                       svn_wc_adm_access_t *adm_access,
 
470
                       apr_pool_t *pool)
 
471
{
 
472
  return svn_wc__text_modified_internal_p(modified_p, filename,
 
473
                                          force_comparison, adm_access,
 
474
                                          TRUE, pool);
 
475
}
 
476
 
479
477
 
480
478
 
481
479
svn_error_t *
482
 
svn_wc_conflicted_p (svn_boolean_t *text_conflicted_p,
483
 
                     svn_boolean_t *prop_conflicted_p,
484
 
                     const char *dir_path,
485
 
                     const svn_wc_entry_t *entry,
486
 
                     apr_pool_t *pool)
 
480
svn_wc_conflicted_p(svn_boolean_t *text_conflicted_p,
 
481
                    svn_boolean_t *prop_conflicted_p,
 
482
                    const char *dir_path,
 
483
                    const svn_wc_entry_t *entry,
 
484
                    apr_pool_t *pool)
487
485
{
488
486
  const char *path;
489
487
  svn_node_kind_t kind;
490
 
  apr_pool_t *subpool = svn_pool_create (pool);  /* ### Why? */
 
488
  apr_pool_t *subpool = svn_pool_create(pool);  /* ### Why? */
491
489
 
492
490
  *text_conflicted_p = FALSE;
493
491
  *prop_conflicted_p = FALSE;
500
498
     conflict file still exists on disk.  */
501
499
  if (entry->conflict_old)
502
500
    {
503
 
      path = svn_path_join (dir_path, entry->conflict_old, subpool);
504
 
      SVN_ERR (svn_io_check_path (path, &kind, subpool));
 
501
      path = svn_path_join(dir_path, entry->conflict_old, subpool);
 
502
      SVN_ERR(svn_io_check_path(path, &kind, subpool));
505
503
      if (kind == svn_node_file)
506
504
        *text_conflicted_p = TRUE;
507
505
    }
508
506
 
509
507
  if ((! *text_conflicted_p) && (entry->conflict_new))
510
508
    {
511
 
      path = svn_path_join (dir_path, entry->conflict_new, subpool);
512
 
      SVN_ERR (svn_io_check_path (path, &kind, subpool));
 
509
      path = svn_path_join(dir_path, entry->conflict_new, subpool);
 
510
      SVN_ERR(svn_io_check_path(path, &kind, subpool));
513
511
      if (kind == svn_node_file)
514
512
        *text_conflicted_p = TRUE;
515
513
    }
516
514
 
517
515
  if ((! *text_conflicted_p) && (entry->conflict_wrk))
518
516
    {
519
 
      path = svn_path_join (dir_path, entry->conflict_wrk, subpool);
520
 
      SVN_ERR (svn_io_check_path (path, &kind, subpool));
 
517
      path = svn_path_join(dir_path, entry->conflict_wrk, subpool);
 
518
      SVN_ERR(svn_io_check_path(path, &kind, subpool));
521
519
      if (kind == svn_node_file)
522
520
        *text_conflicted_p = TRUE;
523
521
    }
525
523
  /* What about prop conflicts? */
526
524
  if (entry->prejfile)
527
525
    {
528
 
      path = svn_path_join (dir_path, entry->prejfile, subpool);
529
 
      SVN_ERR (svn_io_check_path (path, &kind, subpool));
 
526
      path = svn_path_join(dir_path, entry->prejfile, subpool);
 
527
      SVN_ERR(svn_io_check_path(path, &kind, subpool));
530
528
      if (kind == svn_node_file)
531
529
        *prop_conflicted_p = TRUE;
532
530
    }
533
531
  
534
 
  svn_pool_destroy (subpool);
 
532
  svn_pool_destroy(subpool);
535
533
  return SVN_NO_ERROR;
536
534
}
537
535
 
540
538
 
541
539
 
542
540
svn_error_t *
543
 
svn_wc_has_binary_prop (svn_boolean_t *has_binary_prop,
544
 
                        const char *path,
545
 
                        svn_wc_adm_access_t *adm_access,
546
 
                        apr_pool_t *pool)
 
541
svn_wc_has_binary_prop(svn_boolean_t *has_binary_prop,
 
542
                       const char *path,
 
543
                       svn_wc_adm_access_t *adm_access,
 
544
                       apr_pool_t *pool)
547
545
{
548
546
  const svn_string_t *value;
549
 
  apr_pool_t *subpool = svn_pool_create (pool);
 
547
  apr_pool_t *subpool = svn_pool_create(pool);
550
548
 
551
 
  SVN_ERR (svn_wc_prop_get (&value, SVN_PROP_MIME_TYPE, path, adm_access,
552
 
                            subpool));
 
549
  SVN_ERR(svn_wc_prop_get(&value, SVN_PROP_MIME_TYPE, path, adm_access,
 
550
                          subpool));
553
551
 
554
 
  if (value && (svn_mime_type_is_binary (value->data)))
 
552
  if (value && (svn_mime_type_is_binary(value->data)))
555
553
    *has_binary_prop = TRUE;
556
554
  else
557
555
    *has_binary_prop = FALSE;
558
556
  
559
 
  svn_pool_destroy (subpool);
 
557
  svn_pool_destroy(subpool);
560
558
  return SVN_NO_ERROR;
561
559
}