You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/11/30 11:24:23 UTC
svn commit: r1717223 [13/50] - in /subversion/branches/ra-git: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/
contrib/hook-scripts/ notes/ notes/api-errata/1.9/ notes/move-tracking/
subversion/ subversion/bindings/ctypes-python/...
Modified: subversion/branches/ra-git/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_diff/diff_file.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_diff/diff_file.c Mon Nov 30 10:24:16 2015
@@ -777,7 +777,6 @@ datasources_open(void *baton,
{
svn_diff__file_baton_t *file_baton = baton;
struct file_info files[4];
- apr_finfo_t finfo[4];
apr_off_t length[4];
#ifndef SVN_DISABLE_PREFIX_SUFFIX_SCANNING
svn_boolean_t reached_one_eof;
@@ -792,14 +791,14 @@ datasources_open(void *baton,
/* Open datasources and read first chunk */
for (i = 0; i < datasources_len; i++)
{
+ svn_filesize_t filesize;
struct file_info *file
= &file_baton->files[datasource_to_index(datasources[i])];
SVN_ERR(svn_io_file_open(&file->file, file->path,
APR_READ, APR_OS_DEFAULT, file_baton->pool));
- SVN_ERR(svn_io_file_info_get(&finfo[i], APR_FINFO_SIZE,
- file->file, file_baton->pool));
- file->size = finfo[i].size;
- length[i] = finfo[i].size > CHUNK_SIZE ? CHUNK_SIZE : finfo[i].size;
+ SVN_ERR(svn_io_file_size_get(&filesize, file->file, file_baton->pool));
+ file->size = filesize;
+ length[i] = filesize > CHUNK_SIZE ? CHUNK_SIZE : filesize;
file->buffer = apr_palloc(file_baton->pool, (apr_size_t) length[i]);
SVN_ERR(read_chunk(file->file, file->buffer,
length[i], 0, file_baton->pool));
@@ -1243,17 +1242,20 @@ svn_diff_file_options_parse(svn_diff_fil
{
apr_getopt_t *os;
struct opt_parsing_error_baton_t opt_parsing_error_baton;
- /* Make room for each option (starting at index 1) plus trailing NULL. */
- const char **argv = apr_palloc(pool, sizeof(char*) * (args->nelts + 2));
+ apr_array_header_t *argv;
opt_parsing_error_baton.err = NULL;
opt_parsing_error_baton.pool = pool;
- argv[0] = "";
- memcpy(argv + 1, args->elts, sizeof(char*) * args->nelts);
- argv[args->nelts + 1] = NULL;
-
- apr_getopt_init(&os, pool, args->nelts + 1, argv);
+ /* Make room for each option (starting at index 1) plus trailing NULL. */
+ argv = apr_array_make(pool, args->nelts + 2, sizeof(char*));
+ APR_ARRAY_PUSH(argv, const char *) = "";
+ apr_array_cat(argv, args);
+ APR_ARRAY_PUSH(argv, const char *) = NULL;
+
+ apr_getopt_init(&os, pool,
+ argv->nelts - 1 /* Exclude trailing NULL */,
+ (const char *const *) argv->elts);
/* Capture any error message from apr_getopt_long(). This will typically
* say which option is wrong, which we would not otherwise know. */
@@ -1417,6 +1419,10 @@ typedef struct svn_diff__file_output_bat
int context_size;
+ /* Cancel handler */
+ svn_cancel_func_t cancel_func;
+ void *cancel_baton;
+
apr_pool_t *pool;
} svn_diff__file_output_baton_t;
@@ -1598,10 +1604,15 @@ static APR_INLINE svn_error_t *
output_unified_diff_range(svn_diff__file_output_baton_t *output_baton,
int source,
svn_diff__file_output_unified_type_e type,
- apr_off_t until)
+ apr_off_t until,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton)
{
while (output_baton->current_line[source] < until)
{
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
+
SVN_ERR(output_unified_line(output_baton, type, source));
}
return SVN_NO_ERROR;
@@ -1627,7 +1638,8 @@ output_unified_flush_hunk(svn_diff__file
/* Add trailing context to the hunk */
SVN_ERR(output_unified_diff_range(baton, 0 /* original */,
svn_diff__file_output_unified_context,
- target_line));
+ target_line,
+ baton->cancel_func, baton->cancel_baton));
old_start = baton->hunk_start[0];
new_start = baton->hunk_start[1];
@@ -1715,7 +1727,9 @@ output_unified_diff_modified(void *baton
/* Original: Output the context preceding the changed range */
SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
svn_diff__file_output_unified_context,
- original_start));
+ original_start,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
}
}
@@ -1723,7 +1737,9 @@ output_unified_diff_modified(void *baton
to display */
SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
svn_diff__file_output_unified_skip,
- original_start - context_prefix_length));
+ original_start - context_prefix_length,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
/* Note that the above skip stores data for the show_c_function support below */
@@ -1769,20 +1785,28 @@ output_unified_diff_modified(void *baton
/* Modified: Skip lines until we are at the start of the changed range */
SVN_ERR(output_unified_diff_range(output_baton, 1 /* modified */,
svn_diff__file_output_unified_skip,
- modified_start));
+ modified_start,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
/* Original: Output the context preceding the changed range */
SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
svn_diff__file_output_unified_context,
- original_start));
+ original_start,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
/* Both: Output the changed range */
SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
svn_diff__file_output_unified_delete,
- original_start + original_length));
+ original_start + original_length,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
SVN_ERR(output_unified_diff_range(output_baton, 1 /* modified */,
svn_diff__file_output_unified_insert,
- modified_start + modified_length));
+ modified_start + modified_length,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
return SVN_NO_ERROR;
}
@@ -1843,6 +1867,8 @@ svn_diff_file_output_unified4(svn_stream
memset(&baton, 0, sizeof(baton));
baton.output_stream = output_stream;
+ baton.cancel_func = cancel_func;
+ baton.cancel_baton = cancel_baton;
baton.pool = pool;
baton.header_encoding = header_encoding;
baton.path[0] = original_path;
@@ -1956,7 +1982,7 @@ typedef struct context_saver_t {
const char **data; /* const char *data[context_size] */
apr_size_t *len; /* apr_size_t len[context_size] */
apr_size_t next_slot;
- apr_size_t total_written;
+ apr_ssize_t total_writes;
} context_saver_t;
@@ -1972,7 +1998,7 @@ context_saver_stream_write(void *baton,
cs->data[cs->next_slot] = data;
cs->len[cs->next_slot] = *len;
cs->next_slot = (cs->next_slot + 1) % cs->context_size;
- cs->total_written++;
+ cs->total_writes++;
}
return SVN_NO_ERROR;
}
@@ -2252,7 +2278,7 @@ output_conflict_with_context(svn_diff3__
trailing context)? If so, flush it. */
if (btn->output_stream == btn->context_saver->stream)
{
- if (btn->context_saver->total_written > btn->context_size)
+ if (btn->context_saver->total_writes > btn->context_size)
SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n"));
SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream));
}
@@ -2360,7 +2386,7 @@ svn_diff_file_output_merge3(svn_stream_t
svn_diff_conflict_display_style_t style,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
svn_diff3__file_output_baton_t baton;
apr_file_t *file[3];
@@ -2376,7 +2402,7 @@ svn_diff_file_output_merge3(svn_stream_t
baton.context_size = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
if (conflicts_only)
{
- baton.pool = svn_pool_create(pool);
+ baton.pool = svn_pool_create(scratch_pool);
make_context_saver(&baton);
baton.real_output_stream = output_stream;
}
@@ -2387,22 +2413,22 @@ svn_diff_file_output_merge3(svn_stream_t
baton.path[2] = latest_path;
SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_modified,
conflict_modified ? conflict_modified
- : apr_psprintf(pool, "<<<<<<< %s",
+ : apr_psprintf(scratch_pool, "<<<<<<< %s",
modified_path),
- pool));
+ scratch_pool));
SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_original,
conflict_original ? conflict_original
- : apr_psprintf(pool, "||||||| %s",
+ : apr_psprintf(scratch_pool, "||||||| %s",
original_path),
- pool));
+ scratch_pool));
SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_separator,
conflict_separator ? conflict_separator
- : "=======", pool));
+ : "=======", scratch_pool));
SVN_ERR(svn_utf_cstring_from_utf8(&baton.conflict_latest,
conflict_latest ? conflict_latest
- : apr_psprintf(pool, ">>>>>>> %s",
+ : apr_psprintf(scratch_pool, ">>>>>>> %s",
latest_path),
- pool));
+ scratch_pool));
baton.conflict_style = style;
@@ -2413,7 +2439,7 @@ svn_diff_file_output_merge3(svn_stream_t
SVN_ERR(map_or_read_file(&file[idx],
MMAP_T_ARG(mm[idx])
&baton.buffer[idx], &size,
- baton.path[idx], pool));
+ baton.path[idx], scratch_pool));
baton.curp[idx] = baton.buffer[idx];
baton.endp[idx] = baton.buffer[idx];
@@ -2454,7 +2480,7 @@ svn_diff_file_output_merge3(svn_stream_t
if (file[idx])
{
- SVN_ERR(svn_io_file_close(file[idx], pool));
+ SVN_ERR(svn_io_file_close(file[idx], scratch_pool));
}
}
Modified: subversion/branches/ra-git/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_diff/diff_memory.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_diff/diff_memory.c Mon Nov 30 10:24:16 2015
@@ -622,7 +622,7 @@ svn_diff_mem_string_output_unified3(svn_
int context_size,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
if (svn_diff_contains_diffs(diff))
@@ -631,9 +631,9 @@ svn_diff_mem_string_output_unified3(svn_
memset(&baton, 0, sizeof(baton));
baton.output_stream = output_stream;
- baton.pool = svn_pool_create(pool);
+ baton.pool = svn_pool_create(scratch_pool);
baton.header_encoding = header_encoding;
- baton.hunk = svn_stringbuf_create_empty(pool);
+ baton.hunk = svn_stringbuf_create_empty(scratch_pool);
baton.hunk_delimiter = hunk_delimiter;
baton.no_newline_string
= (hunk_delimiter == NULL || strcmp(hunk_delimiter, "##") != 0)
@@ -644,22 +644,22 @@ svn_diff_mem_string_output_unified3(svn_
SVN_ERR(svn_utf_cstring_from_utf8_ex2
(&(baton.prefix_str[unified_output_context]), " ",
- header_encoding, pool));
+ header_encoding, scratch_pool));
SVN_ERR(svn_utf_cstring_from_utf8_ex2
(&(baton.prefix_str[unified_output_delete]), "-",
- header_encoding, pool));
+ header_encoding, scratch_pool));
SVN_ERR(svn_utf_cstring_from_utf8_ex2
(&(baton.prefix_str[unified_output_insert]), "+",
- header_encoding, pool));
+ header_encoding, scratch_pool));
- fill_source_tokens(&baton.sources[0], original, pool);
- fill_source_tokens(&baton.sources[1], modified, pool);
+ fill_source_tokens(&baton.sources[0], original, scratch_pool);
+ fill_source_tokens(&baton.sources[1], modified, scratch_pool);
if (with_diff_header)
{
SVN_ERR(svn_diff__unidiff_write_header(
output_stream, header_encoding,
- original_header, modified_header, pool));
+ original_header, modified_header, scratch_pool));
}
SVN_ERR(svn_diff_output2(diff, &baton,
@@ -688,7 +688,7 @@ typedef struct context_saver_t {
const char **data; /* const char *data[context_size] */
apr_size_t *len; /* apr_size_t len[context_size] */
apr_size_t next_slot;
- apr_size_t total_written;
+ apr_ssize_t total_writes;
} context_saver_t;
@@ -701,7 +701,7 @@ context_saver_stream_write(void *baton,
cs->data[cs->next_slot] = data;
cs->len[cs->next_slot] = *len;
cs->next_slot = (cs->next_slot + 1) % cs->context_size;
- cs->total_written++;
+ cs->total_writes++;
return SVN_NO_ERROR;
}
@@ -822,13 +822,11 @@ make_trailing_context_printer(merge_outp
static svn_error_t *
-output_merge_token_range(apr_size_t *lines_printed_p,
- merge_output_baton_t *btn,
+output_merge_token_range(merge_output_baton_t *btn,
int idx, apr_off_t first,
apr_off_t length)
{
apr_array_header_t *tokens = btn->sources[idx].tokens;
- apr_size_t lines_printed = 0;
for (; length > 0 && first < tokens->nelts; length--, first++)
{
@@ -838,12 +836,8 @@ output_merge_token_range(apr_size_t *lin
/* Note that the trailing context printer assumes that
svn_stream_write is called exactly once per line. */
SVN_ERR(svn_stream_write(btn->output_stream, token->data, &len));
- lines_printed++;
}
- if (lines_printed_p)
- *lines_printed_p = lines_printed;
-
return SVN_NO_ERROR;
}
@@ -866,7 +860,7 @@ output_common_modified(void *baton,
apr_off_t modified_start, apr_off_t modified_length,
apr_off_t latest_start, apr_off_t latest_length)
{
- return output_merge_token_range(NULL, baton, 1/*modified*/,
+ return output_merge_token_range(baton, 1/*modified*/,
modified_start, modified_length);
}
@@ -876,7 +870,7 @@ output_latest(void *baton,
apr_off_t modified_start, apr_off_t modified_length,
apr_off_t latest_start, apr_off_t latest_length)
{
- return output_merge_token_range(NULL, baton, 2/*latest*/,
+ return output_merge_token_range(baton, 2/*latest*/,
latest_start, latest_length);
}
@@ -920,26 +914,26 @@ output_conflict(void *baton,
style == svn_diff_conflict_display_modified_original_latest)
{
SVN_ERR(output_merge_marker(btn, 1/*modified*/));
- SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/,
+ SVN_ERR(output_merge_token_range(btn, 1/*modified*/,
modified_start, modified_length));
if (style == svn_diff_conflict_display_modified_original_latest)
{
SVN_ERR(output_merge_marker(btn, 0/*original*/));
- SVN_ERR(output_merge_token_range(NULL, btn, 0/*original*/,
+ SVN_ERR(output_merge_token_range(btn, 0/*original*/,
original_start, original_length));
}
SVN_ERR(output_merge_marker(btn, 2/*separator*/));
- SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/,
+ SVN_ERR(output_merge_token_range(btn, 2/*latest*/,
latest_start, latest_length));
SVN_ERR(output_merge_marker(btn, 3/*latest (end)*/));
}
else if (style == svn_diff_conflict_display_modified)
- SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/,
+ SVN_ERR(output_merge_token_range(btn, 1/*modified*/,
modified_start, modified_length));
else if (style == svn_diff_conflict_display_latest)
- SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/,
+ SVN_ERR(output_merge_token_range(btn, 2/*latest*/,
latest_start, latest_length));
else /* unknown style */
SVN_ERR_MALFUNCTION();
@@ -983,7 +977,7 @@ output_conflict_with_context(void *baton
trailing context)? If so, flush it. */
if (btn->output_stream == btn->context_saver->stream)
{
- if (btn->context_saver->total_written > btn->context_size)
+ if (btn->context_saver->total_writes > btn->context_size)
SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n"));
SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream));
}
@@ -995,17 +989,17 @@ output_conflict_with_context(void *baton
SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[1],
modified_start,
modified_length));
- SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/,
+ SVN_ERR(output_merge_token_range(btn, 1/*modified*/,
modified_start, modified_length));
SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[0],
original_start,
original_length));
- SVN_ERR(output_merge_token_range(NULL, btn, 0/*original*/,
+ SVN_ERR(output_merge_token_range(btn, 0/*original*/,
original_start, original_length));
SVN_ERR(output_merge_marker(btn, 2/*separator*/));
- SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/,
+ SVN_ERR(output_merge_token_range(btn, 2/*latest*/,
latest_start, latest_length));
SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[3],
latest_start,
@@ -1066,7 +1060,7 @@ svn_diff_mem_string_output_merge3(svn_st
svn_diff_conflict_display_style_t style,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
merge_output_baton_t btn;
const char *eol;
@@ -1080,16 +1074,16 @@ svn_diff_mem_string_output_merge3(svn_st
if (conflicts_only)
{
- btn.pool = svn_pool_create(pool);
+ btn.pool = svn_pool_create(scratch_pool);
make_context_saver(&btn);
btn.real_output_stream = output_stream;
}
else
btn.output_stream = output_stream;
- fill_source_tokens(&(btn.sources[0]), original, pool);
- fill_source_tokens(&(btn.sources[1]), modified, pool);
- fill_source_tokens(&(btn.sources[2]), latest, pool);
+ fill_source_tokens(&(btn.sources[0]), original, scratch_pool);
+ fill_source_tokens(&(btn.sources[1]), modified, scratch_pool);
+ fill_source_tokens(&(btn.sources[2]), latest, scratch_pool);
btn.conflict_style = style;
@@ -1110,22 +1104,22 @@ svn_diff_mem_string_output_merge3(svn_st
conflict_modified
? conflict_modified
: "<<<<<<< (modified)",
- pool));
+ scratch_pool));
SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[0],
conflict_original
? conflict_original
: "||||||| (original)",
- pool));
+ scratch_pool));
SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[2],
conflict_separator
? conflict_separator
: "=======",
- pool));
+ scratch_pool));
SVN_ERR(svn_utf_cstring_from_utf8(&btn.markers[3],
conflict_latest
? conflict_latest
: ">>>>>>> (latest)",
- pool));
+ scratch_pool));
SVN_ERR(svn_diff_output2(diff, &btn, vtable, cancel_func, cancel_baton));
if (conflicts_only)
Modified: subversion/branches/ra-git/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_diff/parse-diff.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_diff/parse-diff.c Mon Nov 30 10:24:16 2015
@@ -40,8 +40,13 @@
#include "private/svn_eol_private.h"
#include "private/svn_dep_compat.h"
+#include "private/svn_diff_private.h"
#include "private/svn_sorts_private.h"
+#include "diff.h"
+
+#include "svn_private_config.h"
+
/* Helper macro for readability */
#define starts_with(str, start) \
(strncmp((str), (start), strlen(start)) == 0)
@@ -59,7 +64,7 @@ struct svn_diff__hunk_range {
struct svn_diff_hunk_t {
/* The patch this hunk belongs to. */
- svn_patch_t *patch;
+ const svn_patch_t *patch;
/* APR file handle to the patch file this hunk came from. */
apr_file_t *apr_file;
@@ -80,8 +85,146 @@ struct svn_diff_hunk_t {
/* Number of lines of leading and trailing hunk context. */
svn_linenum_t leading_context;
svn_linenum_t trailing_context;
+
+ /* Did we see a 'file does not end with eol' marker in this hunk? */
+ svn_boolean_t original_no_final_eol;
+ svn_boolean_t modified_no_final_eol;
};
+struct svn_diff_binary_patch_t {
+ /* The patch this hunk belongs to. */
+ const svn_patch_t *patch;
+
+ /* APR file handle to the patch file this hunk came from. */
+ apr_file_t *apr_file;
+
+ /* Offsets inside APR_FILE representing the location of the patch */
+ apr_off_t src_start;
+ apr_off_t src_end;
+ svn_filesize_t src_filesize; /* Expanded/final size */
+
+ /* Offsets inside APR_FILE representing the location of the patch */
+ apr_off_t dst_start;
+ apr_off_t dst_end;
+ svn_filesize_t dst_filesize; /* Expanded/final size */
+};
+
+/* Common guts of svn_diff_hunk__create_adds_single_line() and
+ * svn_diff_hunk__create_deletes_single_line().
+ *
+ * ADD is TRUE if adding and FALSE if deleting.
+ */
+static svn_error_t *
+add_or_delete_single_line(svn_diff_hunk_t **hunk_out,
+ const char *line,
+ const svn_patch_t *patch,
+ svn_boolean_t add,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_diff_hunk_t *hunk = apr_palloc(result_pool, sizeof(*hunk));
+ static const char *hunk_header[] = { "@@ -1 +0,0 @@\n", "@@ -0,0 +1 @@\n" };
+ const apr_size_t header_len = strlen(hunk_header[add]);
+ const apr_size_t len = strlen(line);
+ const apr_size_t end = header_len + (1 + len); /* The +1 is for the \n. */
+ svn_stringbuf_t *buf = svn_stringbuf_create_ensure(end + 1, scratch_pool);
+
+ hunk->patch = patch;
+
+ /* hunk->apr_file is created below. */
+
+ hunk->diff_text_range.start = header_len;
+ hunk->diff_text_range.current = header_len;
+
+ if (add)
+ {
+ hunk->original_text_range.start = 0; /* There's no "original" text. */
+ hunk->original_text_range.current = 0;
+ hunk->original_text_range.end = 0;
+ hunk->original_no_final_eol = FALSE;
+
+ hunk->modified_text_range.start = header_len;
+ hunk->modified_text_range.current = header_len;
+ hunk->modified_text_range.end = end;
+ hunk->modified_no_final_eol = TRUE;
+
+ hunk->original_start = 0;
+ hunk->original_length = 0;
+
+ hunk->modified_start = 1;
+ hunk->modified_length = 1;
+ }
+ else /* delete */
+ {
+ hunk->original_text_range.start = header_len;
+ hunk->original_text_range.current = header_len;
+ hunk->original_text_range.end = end;
+ hunk->original_no_final_eol = TRUE;
+
+ hunk->modified_text_range.start = 0; /* There's no "original" text. */
+ hunk->modified_text_range.current = 0;
+ hunk->modified_text_range.end = 0;
+ hunk->modified_no_final_eol = FALSE;
+
+ hunk->original_start = 1;
+ hunk->original_length = 1;
+
+ hunk->modified_start = 0;
+ hunk->modified_length = 0; /* setting to '1' works too */
+ }
+
+ hunk->leading_context = 0;
+ hunk->trailing_context = 0;
+
+ /* Create APR_FILE and put just a hunk in it (without a diff header).
+ * Save the offset of the last byte of the diff line. */
+ svn_stringbuf_appendbytes(buf, hunk_header[add], header_len);
+ svn_stringbuf_appendbyte(buf, add ? '+' : '-');
+ svn_stringbuf_appendbytes(buf, line, len);
+ svn_stringbuf_appendbyte(buf, '\n');
+ svn_stringbuf_appendcstr(buf, "\\ No newline at end of hunk\n");
+
+ hunk->diff_text_range.end = buf->len;
+
+ SVN_ERR(svn_io_open_unique_file3(&hunk->apr_file, NULL /* filename */,
+ NULL /* system tempdir */,
+ svn_io_file_del_on_pool_cleanup,
+ result_pool, scratch_pool));
+ SVN_ERR(svn_io_file_write_full(hunk->apr_file,
+ buf->data, buf->len,
+ NULL, scratch_pool));
+ /* No need to seek. */
+
+ *hunk_out = hunk;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_diff_hunk__create_adds_single_line(svn_diff_hunk_t **hunk_out,
+ const char *line,
+ const svn_patch_t *patch,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(add_or_delete_single_line(hunk_out, line, patch,
+ (!patch->reverse),
+ result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_diff_hunk__create_deletes_single_line(svn_diff_hunk_t **hunk_out,
+ const char *line,
+ const svn_patch_t *patch,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(add_or_delete_single_line(hunk_out, line, patch,
+ patch->reverse,
+ result_pool, scratch_pool));
+ return SVN_NO_ERROR;
+}
+
void
svn_diff_hunk_reset_diff_text(svn_diff_hunk_t *hunk)
{
@@ -142,6 +285,217 @@ svn_diff_hunk_get_trailing_context(const
return hunk->trailing_context;
}
+/* Baton for the base85 stream implementation */
+struct base85_baton_t
+{
+ apr_file_t *file;
+ apr_pool_t *iterpool;
+ char buffer[52]; /* Bytes on current line */
+ apr_off_t next_pos; /* Start position of next line */
+ apr_off_t end_pos; /* Position after last line */
+ apr_size_t buf_size; /* Bytes available (52 unless at eof) */
+ apr_size_t buf_pos; /* Bytes in linebuffer */
+ svn_boolean_t done; /* At eof? */
+};
+
+/* Implements svn_read_fn_t for the base85 read stream */
+static svn_error_t *
+read_handler_base85(void *baton, char *buffer, apr_size_t *len)
+{
+ struct base85_baton_t *b85b = baton;
+ apr_pool_t *iterpool = b85b->iterpool;
+ apr_size_t remaining = *len;
+ char *dest = buffer;
+
+ svn_pool_clear(iterpool);
+
+ if (b85b->done)
+ {
+ *len = 0;
+ return SVN_NO_ERROR;
+ }
+
+ while (remaining && (b85b->buf_size > b85b->buf_pos
+ || b85b->next_pos < b85b->end_pos))
+ {
+ svn_stringbuf_t *line;
+ svn_boolean_t at_eof;
+
+ apr_size_t available = b85b->buf_size - b85b->buf_pos;
+ if (available)
+ {
+ apr_size_t n = (remaining < available) ? remaining : available;
+
+ memcpy(dest, b85b->buffer + b85b->buf_pos, n);
+ dest += n;
+ remaining -= n;
+ b85b->buf_pos += n;
+
+ if (!remaining)
+ return SVN_NO_ERROR; /* *len = OK */
+ }
+
+ if (b85b->next_pos >= b85b->end_pos)
+ break; /* At EOF */
+ SVN_ERR(svn_io_file_seek(b85b->file, APR_SET, &b85b->next_pos,
+ iterpool));
+ SVN_ERR(svn_io_file_readline(b85b->file, &line, NULL, &at_eof,
+ APR_SIZE_MAX, iterpool, iterpool));
+ if (at_eof)
+ b85b->next_pos = b85b->end_pos;
+ else
+ {
+ b85b->next_pos = 0;
+ SVN_ERR(svn_io_file_seek(b85b->file, APR_CUR, &b85b->next_pos,
+ iterpool));
+ }
+
+ if (line->len && line->data[0] >= 'A' && line->data[0] <= 'Z')
+ b85b->buf_size = line->data[0] - 'A' + 1;
+ else if (line->len && line->data[0] >= 'a' && line->data[0] <= 'z')
+ b85b->buf_size = line->data[0] - 'a' + 26 + 1;
+ else
+ return svn_error_create(SVN_ERR_DIFF_UNEXPECTED_DATA, NULL,
+ _("Unexpected data in base85 section"));
+
+ if (b85b->buf_size < 52)
+ b85b->next_pos = b85b->end_pos; /* Handle as EOF */
+
+ SVN_ERR(svn_diff__base85_decode_line(b85b->buffer, b85b->buf_size,
+ line->data + 1, line->len - 1,
+ iterpool));
+ b85b->buf_pos = 0;
+ }
+
+ *len -= remaining;
+ b85b->done = TRUE;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_close_fn_t for the base85 read stream */
+static svn_error_t *
+close_handler_base85(void *baton)
+{
+ struct base85_baton_t *b85b = baton;
+
+ svn_pool_destroy(b85b->iterpool);
+
+ return SVN_NO_ERROR;
+}
+
+/* Gets a stream that reads decoded base85 data from a segment of a file.
+ The current implementation might assume that both start_pos and end_pos
+ are located at line boundaries. */
+static svn_stream_t *
+get_base85_data_stream(apr_file_t *file,
+ apr_off_t start_pos,
+ apr_off_t end_pos,
+ apr_pool_t *result_pool)
+{
+ struct base85_baton_t *b85b = apr_pcalloc(result_pool, sizeof(*b85b));
+ svn_stream_t *base85s = svn_stream_create(b85b, result_pool);
+
+ b85b->file = file;
+ b85b->iterpool = svn_pool_create(result_pool);
+ b85b->next_pos = start_pos;
+ b85b->end_pos = end_pos;
+
+ svn_stream_set_read2(base85s, NULL /* only full read support */,
+ read_handler_base85);
+ svn_stream_set_close(base85s, close_handler_base85);
+ return base85s;
+}
+
+/* Baton for the length verification stream functions */
+struct length_verify_baton_t
+{
+ svn_stream_t *inner;
+ svn_filesize_t remaining;
+};
+
+/* Implements svn_read_fn_t for the length verification stream */
+static svn_error_t *
+read_handler_length_verify(void *baton, char *buffer, apr_size_t *len)
+{
+ struct length_verify_baton_t *lvb = baton;
+ apr_size_t requested_len = *len;
+
+ SVN_ERR(svn_stream_read_full(lvb->inner, buffer, len));
+
+ if (*len > lvb->remaining)
+ return svn_error_create(SVN_ERR_DIFF_UNEXPECTED_DATA, NULL,
+ _("Base85 data expands to longer than declared "
+ "filesize"));
+ else if (requested_len > *len && *len != lvb->remaining)
+ return svn_error_create(SVN_ERR_DIFF_UNEXPECTED_DATA, NULL,
+ _("Base85 data expands to smaller than declared "
+ "filesize"));
+
+ lvb->remaining -= *len;
+
+ return SVN_NO_ERROR;
+}
+
+/* Implements svn_close_fn_t for the length verification stream */
+static svn_error_t *
+close_handler_length_verify(void *baton)
+{
+ struct length_verify_baton_t *lvb = baton;
+
+ return svn_error_trace(svn_stream_close(lvb->inner));
+}
+
+/* Gets a stream that verifies on reads that the inner stream is exactly
+ of the specified length */
+static svn_stream_t *
+get_verify_length_stream(svn_stream_t *inner,
+ svn_filesize_t expected_size,
+ apr_pool_t *result_pool)
+{
+ struct length_verify_baton_t *lvb = apr_palloc(result_pool, sizeof(*lvb));
+ svn_stream_t *len_stream = svn_stream_create(lvb, result_pool);
+
+ lvb->inner = inner;
+ lvb->remaining = expected_size;
+
+ svn_stream_set_read2(len_stream, NULL /* only full read support */,
+ read_handler_length_verify);
+ svn_stream_set_close(len_stream, close_handler_length_verify);
+
+ return len_stream;
+}
+
+svn_stream_t *
+svn_diff_get_binary_diff_original_stream(const svn_diff_binary_patch_t *bpatch,
+ apr_pool_t *result_pool)
+{
+ svn_stream_t *s = get_base85_data_stream(bpatch->apr_file, bpatch->src_start,
+ bpatch->src_end, result_pool);
+
+ s = svn_stream_compressed(s, result_pool);
+
+ /* ### If we (ever) want to support the DELTA format, then we should hook the
+ undelta handling here */
+
+ return get_verify_length_stream(s, bpatch->src_filesize, result_pool);
+}
+
+svn_stream_t *
+svn_diff_get_binary_diff_result_stream(const svn_diff_binary_patch_t *bpatch,
+ apr_pool_t *result_pool)
+{
+ svn_stream_t *s = get_base85_data_stream(bpatch->apr_file, bpatch->dst_start,
+ bpatch->dst_end, result_pool);
+
+ s = svn_stream_compressed(s, result_pool);
+
+ /* ### If we (ever) want to support the DELTA format, then we should hook the
+ undelta handling here */
+
+ return get_verify_length_stream(s, bpatch->dst_filesize, result_pool);
+}
+
/* Try to parse a positive number from a decimal number encoded
* in the string NUMBER. Return parsed number in OFFSET, and return
* TRUE if parsing was successful. */
@@ -279,7 +633,8 @@ parse_hunk_header(const char *header, sv
* Leading unidiff symbols ('+', '-', and ' ') are removed from the line,
* Any lines commencing with the VERBOTEN character are discarded.
* VERBOTEN should be '+' or '-', depending on which form of hunk text
- * is being read.
+ * is being read. NO_FINAL_EOL declares if the hunk contains a no final
+ * EOL marker.
*
* All other parameters are as in svn_diff_hunk_readline_original_text()
* and svn_diff_hunk_readline_modified_text().
@@ -291,6 +646,7 @@ hunk_readline_original_or_modified(apr_f
const char **eol,
svn_boolean_t *eof,
char verboten,
+ svn_boolean_t no_final_eol,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -298,13 +654,17 @@ hunk_readline_original_or_modified(apr_f
svn_boolean_t filtered;
apr_off_t pos;
svn_stringbuf_t *str;
+ const char *eol_p;
+ apr_pool_t *last_pool;
+
+ if (!eol)
+ eol = &eol_p;
if (range->current >= range->end)
{
/* We're past the range. Indicate that no bytes can be read. */
*eof = TRUE;
- if (eol)
- *eol = NULL;
+ *eol = NULL;
*stringbuf = svn_stringbuf_create_empty(result_pool);
return SVN_NO_ERROR;
}
@@ -312,13 +672,19 @@ hunk_readline_original_or_modified(apr_f
pos = 0;
SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, scratch_pool));
SVN_ERR(svn_io_file_seek(file, APR_SET, &range->current, scratch_pool));
+
+ /* It's not ITERPOOL because we use data allocated in LAST_POOL out
+ of the loop. */
+ last_pool = svn_pool_create(scratch_pool);
do
{
+ svn_pool_clear(last_pool);
+
max_len = range->end - range->current;
SVN_ERR(svn_io_file_readline(file, &str, eol, eof, max_len,
- result_pool, scratch_pool));
+ last_pool, last_pool));
range->current = 0;
- SVN_ERR(svn_io_file_seek(file, APR_CUR, &range->current, scratch_pool));
+ SVN_ERR(svn_io_file_seek(file, APR_CUR, &range->current, last_pool));
filtered = (str->data[0] == verboten || str->data[0] == '\\');
}
while (filtered && ! *eof);
@@ -327,6 +693,7 @@ hunk_readline_original_or_modified(apr_f
{
/* EOF, return an empty string. */
*stringbuf = svn_stringbuf_create_ensure(0, result_pool);
+ *eol = NULL;
}
else if (str->data[0] == '+' || str->data[0] == '-' || str->data[0] == ' ')
{
@@ -335,12 +702,37 @@ hunk_readline_original_or_modified(apr_f
}
else
{
- /* Return the line as-is. */
+ /* Return the line as-is. Handle as a chopped leading spaces */
*stringbuf = svn_stringbuf_dup(str, result_pool);
}
+ if (!filtered && *eof && !*eol && *str->data)
+ {
+ /* Ok, we miss a final EOL in the patch file, but didn't see a
+ no eol marker line.
+
+ We should report that we had an EOL or the patch code will
+ misbehave (and it knows nothing about no eol markers) */
+
+ if (!no_final_eol && eol != &eol_p)
+ {
+ apr_off_t start = 0;
+
+ SVN_ERR(svn_io_file_seek(file, APR_SET, &start, scratch_pool));
+
+ SVN_ERR(svn_io_file_readline(file, &str, eol, NULL, APR_SIZE_MAX,
+ scratch_pool, scratch_pool));
+
+ /* Every patch file that has hunks has at least one EOL*/
+ SVN_ERR_ASSERT(*eol != NULL);
+ }
+
+ *eof = FALSE;
+ /* Fall through to seek back to the right location */
+ }
SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool));
+ svn_pool_destroy(last_pool);
return SVN_NO_ERROR;
}
@@ -359,6 +751,9 @@ svn_diff_hunk_readline_original_text(svn
&hunk->original_text_range,
stringbuf, eol, eof,
hunk->patch->reverse ? '-' : '+',
+ hunk->patch->reverse
+ ? hunk->modified_no_final_eol
+ : hunk->original_no_final_eol,
result_pool, scratch_pool));
}
@@ -377,6 +772,9 @@ svn_diff_hunk_readline_modified_text(svn
&hunk->modified_text_range,
stringbuf, eol, eof,
hunk->patch->reverse ? '+' : '-',
+ hunk->patch->reverse
+ ? hunk->original_no_final_eol
+ : hunk->modified_no_final_eol,
result_pool, scratch_pool));
}
@@ -391,13 +789,16 @@ svn_diff_hunk_readline_diff_text(svn_dif
svn_stringbuf_t *line;
apr_size_t max_len;
apr_off_t pos;
+ const char *eol_p;
+
+ if (!eol)
+ eol = &eol_p;
if (hunk->diff_text_range.current >= hunk->diff_text_range.end)
{
/* We're past the range. Indicate that no bytes can be read. */
*eof = TRUE;
- if (eol)
- *eol = NULL;
+ *eol = NULL;
*stringbuf = svn_stringbuf_create_empty(result_pool);
return SVN_NO_ERROR;
}
@@ -413,6 +814,37 @@ svn_diff_hunk_readline_diff_text(svn_dif
hunk->diff_text_range.current = 0;
SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_CUR,
&hunk->diff_text_range.current, scratch_pool));
+
+ if (*eof && !*eol && *line->data)
+ {
+ /* Ok, we miss a final EOL in the patch file, but didn't see a
+ no eol marker line.
+
+ We should report that we had an EOL or the patch code will
+ misbehave (and it knows nothing about no eol markers) */
+
+ if (eol != &eol_p)
+ {
+ /* Lets pick the first eol we find in our patch file */
+ apr_off_t start = 0;
+ svn_stringbuf_t *str;
+
+ SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET, &start,
+ scratch_pool));
+
+ SVN_ERR(svn_io_file_readline(hunk->apr_file, &str, eol, NULL,
+ APR_SIZE_MAX,
+ scratch_pool, scratch_pool));
+
+ /* Every patch file that has hunks has at least one EOL*/
+ SVN_ERR_ASSERT(*eol != NULL);
+ }
+
+ *eof = FALSE;
+
+ /* Fall through to seek back to the right location */
+ }
+
SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET, &pos, scratch_pool));
if (hunk->patch->reverse)
@@ -619,6 +1051,8 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
apr_off_t start, end;
apr_off_t original_end;
apr_off_t modified_end;
+ svn_boolean_t original_no_final_eol = FALSE;
+ svn_boolean_t modified_no_final_eol = FALSE;
svn_linenum_t original_lines;
svn_linenum_t modified_lines;
svn_linenum_t leading_context;
@@ -715,6 +1149,11 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
}
SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &pos, iterpool));
+ /* Set for the type and context by using != the other type */
+ if (last_line_type != modified_line)
+ original_no_final_eol = TRUE;
+ if (last_line_type != original_line)
+ modified_no_final_eol = TRUE;
}
continue;
@@ -728,7 +1167,13 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
SVN_ERR(parse_mergeinfo(&found_mergeinfo, line, *hunk, patch,
result_pool, iterpool));
if (found_mergeinfo)
- continue; /* Proceed to the next line in the patch. */
+ continue; /* Proceed to the next line in the svn:mergeinfo hunk. */
+ else
+ {
+ /* Perhaps we can also use original_lines/modified_lines here */
+
+ in_hunk = FALSE; /* On to next property */
+ }
}
if (in_hunk)
@@ -843,14 +1288,16 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
SVN_ERR(parse_prop_name(prop_name, line->data, "Added: ",
result_pool));
if (*prop_name)
- *prop_operation = svn_diff_op_added;
+ *prop_operation = (patch->reverse ? svn_diff_op_deleted
+ : svn_diff_op_added);
}
else if (starts_with(line->data, "Deleted: "))
{
SVN_ERR(parse_prop_name(prop_name, line->data, "Deleted: ",
result_pool));
if (*prop_name)
- *prop_operation = svn_diff_op_deleted;
+ *prop_operation = (patch->reverse ? svn_diff_op_added
+ : svn_diff_op_deleted);
}
else if (starts_with(line->data, "Modified: "))
{
@@ -891,6 +1338,8 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
(*hunk)->modified_text_range.start = start;
(*hunk)->modified_text_range.current = start;
(*hunk)->modified_text_range.end = modified_end;
+ (*hunk)->original_no_final_eol = original_no_final_eol;
+ (*hunk)->modified_no_final_eol = modified_no_final_eol;
}
else
/* Something went wrong, just discard the result. */
@@ -917,16 +1366,19 @@ compare_hunks(const void *a, const void
/* Possible states of the diff header parser. */
enum parse_state
{
- state_start, /* initial */
- state_git_diff_seen, /* diff --git */
- state_git_tree_seen, /* a tree operation, rather then content change */
- state_git_minus_seen, /* --- /dev/null; or --- a/ */
- state_git_plus_seen, /* +++ /dev/null; or +++ a/ */
- state_move_from_seen, /* rename from foo.c */
- state_copy_from_seen, /* copy from foo.c */
- state_minus_seen, /* --- foo.c */
- state_unidiff_found, /* valid start of a regular unidiff header */
- state_git_header_found /* valid start of a --git diff header */
+ state_start, /* initial */
+ state_git_diff_seen, /* diff --git */
+ state_git_tree_seen, /* a tree operation, rather than content change */
+ state_git_minus_seen, /* --- /dev/null; or --- a/ */
+ state_git_plus_seen, /* +++ /dev/null; or +++ a/ */
+ state_old_mode_seen, /* old mode 100644 */
+ state_git_mode_seen, /* new mode 100644 */
+ state_move_from_seen, /* rename from foo.c */
+ state_copy_from_seen, /* copy from foo.c */
+ state_minus_seen, /* --- foo.c */
+ state_unidiff_found, /* valid start of a regular unidiff header */
+ state_git_header_found, /* valid start of a --git diff header */
+ state_binary_patch_found /* valid start of binary patch */
};
/* Data type describing a valid state transition of the parser. */
@@ -1153,6 +1605,139 @@ git_plus(enum parse_state *new_state, ch
return SVN_NO_ERROR;
}
+/* Helper for git_old_mode() and git_new_mode(). Translate the git
+ * file mode MODE_STR into a binary "executable?" and "symlink?" state. */
+static svn_error_t *
+parse_git_mode_bits(svn_tristate_t *executable_p,
+ svn_tristate_t *symlink_p,
+ const char *mode_str)
+{
+ apr_uint64_t mode;
+ SVN_ERR(svn_cstring_strtoui64(&mode, mode_str,
+ 0 /* min */,
+ 0777777 /* max: six octal digits */,
+ 010 /* radix (octal) */));
+
+ /* Note: 0644 and 0755 are the only modes that can occur for plain files.
+ * We deliberately choose to parse only those values: we are strict in what
+ * we accept _and_ in what we produce.
+ *
+ * (Having said that, though, we could consider relaxing the parser to also
+ * map
+ * (mode & 0111) == 0000 -> svn_tristate_false
+ * (mode & 0111) == 0111 -> svn_tristate_true
+ * [anything else] -> svn_tristate_unknown
+ * .)
+ */
+
+ switch (mode & 0777)
+ {
+ case 0644:
+ *executable_p = svn_tristate_false;
+ break;
+
+ case 0755:
+ *executable_p = svn_tristate_true;
+ break;
+
+ default:
+ /* Ignore unknown values. */
+ *executable_p = svn_tristate_unknown;
+ break;
+ }
+
+ switch (mode & 0170000 /* S_IFMT */)
+ {
+ case 0120000: /* S_IFLNK */
+ *symlink_p = svn_tristate_true;
+ break;
+
+ case 0100000: /* S_IFREG */
+ case 0040000: /* S_IFDIR */
+ *symlink_p = svn_tristate_false;
+ break;
+
+ default:
+ /* Ignore unknown values.
+ (Including those generated by Subversion <= 1.9) */
+ *symlink_p = svn_tristate_unknown;
+ break;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Parse the 'old mode ' line of a git extended unidiff. */
+static svn_error_t *
+git_old_mode(enum parse_state *new_state, char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ SVN_ERR(parse_git_mode_bits(&patch->old_executable_bit,
+ &patch->old_symlink_bit,
+ line + STRLEN_LITERAL("old mode ")));
+
+#ifdef SVN_DEBUG
+ /* If this assert trips, the "old mode" is neither ...644 nor ...755 . */
+ SVN_ERR_ASSERT(patch->old_executable_bit != svn_tristate_unknown);
+#endif
+
+ *new_state = state_old_mode_seen;
+ return SVN_NO_ERROR;
+}
+
+/* Parse the 'new mode ' line of a git extended unidiff. */
+static svn_error_t *
+git_new_mode(enum parse_state *new_state, char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ SVN_ERR(parse_git_mode_bits(&patch->new_executable_bit,
+ &patch->new_symlink_bit,
+ line + STRLEN_LITERAL("new mode ")));
+
+#ifdef SVN_DEBUG
+ /* If this assert trips, the "old mode" is neither ...644 nor ...755 . */
+ SVN_ERR_ASSERT(patch->new_executable_bit != svn_tristate_unknown);
+#endif
+
+ /* Don't touch patch->operation. */
+
+ *new_state = state_git_mode_seen;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+git_index(enum parse_state *new_state, char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ /* We either have something like "index 33e5b38..0000000" (which we just
+ ignore as we are not interested in git specific shas) or something like
+ "index 33e5b38..0000000 120000" which tells us the mode, that isn't
+ changed by applying this patch.
+
+ If the mode would have changed then we would see 'old mode' and 'new mode'
+ lines.
+ */
+ line = strchr(line + STRLEN_LITERAL("index "), ' ');
+
+ if (line && patch->new_executable_bit == svn_tristate_unknown
+ && patch->new_symlink_bit == svn_tristate_unknown
+ && patch->operation != svn_diff_op_added
+ && patch->operation != svn_diff_op_deleted)
+ {
+ SVN_ERR(parse_git_mode_bits(&patch->new_executable_bit,
+ &patch->new_symlink_bit,
+ line + 1));
+
+ /* There is no change.. so set the old values to the new values */
+ patch->old_executable_bit = patch->new_executable_bit;
+ patch->old_symlink_bit = patch->new_symlink_bit;
+ }
+
+ /* This function doesn't change the state! */
+ /* *new_state = *new_state */
+ return SVN_NO_ERROR;
+}
+
/* Parse the 'rename from ' line of a git extended unidiff. */
static svn_error_t *
git_move_from(enum parse_state *new_state, char *line, svn_patch_t *patch,
@@ -1213,6 +1798,10 @@ static svn_error_t *
git_new_file(enum parse_state *new_state, char *line, svn_patch_t *patch,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
+ SVN_ERR(parse_git_mode_bits(&patch->new_executable_bit,
+ &patch->new_symlink_bit,
+ line + STRLEN_LITERAL("new file mode ")));
+
patch->operation = svn_diff_op_added;
/* Filename already retrieved from diff --git header. */
@@ -1226,6 +1815,10 @@ static svn_error_t *
git_deleted_file(enum parse_state *new_state, char *line, svn_patch_t *patch,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
+ SVN_ERR(parse_git_mode_bits(&patch->old_executable_bit,
+ &patch->old_symlink_bit,
+ line + STRLEN_LITERAL("deleted file mode ")));
+
patch->operation = svn_diff_op_deleted;
/* Filename already retrieved from diff --git header. */
@@ -1234,6 +1827,16 @@ git_deleted_file(enum parse_state *new_s
return SVN_NO_ERROR;
}
+/* Parse the 'GIT binary patch' header */
+static svn_error_t *
+binary_patch_start(enum parse_state *new_state, char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ *new_state = state_binary_patch_found;
+ return SVN_NO_ERROR;
+}
+
+
/* Add a HUNK associated with the property PROP_NAME to PATCH. */
static svn_error_t *
add_property_hunk(svn_patch_t *patch, const char *prop_name,
@@ -1346,24 +1949,165 @@ parse_hunks(svn_patch_t *patch, apr_file
return SVN_NO_ERROR;
}
+static svn_error_t *
+parse_binary_patch(svn_patch_t *patch, apr_file_t *apr_file,
+ svn_boolean_t reverse,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ apr_off_t pos, last_line;
+ svn_stringbuf_t *line;
+ svn_boolean_t eof = FALSE;
+ svn_diff_binary_patch_t *bpatch = apr_pcalloc(result_pool, sizeof(*bpatch));
+ svn_boolean_t in_blob = FALSE;
+ svn_boolean_t in_src = FALSE;
+
+ bpatch->apr_file = apr_file;
+
+ patch->prop_patches = apr_hash_make(result_pool);
+
+ pos = 0;
+ SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, scratch_pool));
+
+ while (!eof)
+ {
+ last_line = pos;
+ SVN_ERR(svn_io_file_readline(apr_file, &line, NULL, &eof, APR_SIZE_MAX,
+ iterpool, iterpool));
+
+ /* Update line offset for next iteration. */
+ pos = 0;
+ SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, iterpool));
+
+ if (in_blob)
+ {
+ char c = line->data[0];
+
+ /* 66 = len byte + (52/4*5) chars */
+ if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
+ && line->len <= 66
+ && !strchr(line->data, ':')
+ && !strchr(line->data, ' '))
+ {
+ /* One more blop line */
+ if (in_src)
+ bpatch->src_end = pos;
+ else
+ bpatch->dst_end = pos;
+ }
+ else if (svn_stringbuf_first_non_whitespace(line) < line->len
+ && !(in_src && bpatch->src_start < last_line))
+ {
+ break; /* Bad patch */
+ }
+ else if (in_src)
+ {
+ patch->binary_patch = bpatch; /* SUCCESS! */
+ break;
+ }
+ else
+ {
+ in_blob = FALSE;
+ in_src = TRUE;
+ }
+ }
+ else if (starts_with(line->data, "literal "))
+ {
+ apr_uint64_t expanded_size;
+ svn_error_t *err = svn_cstring_strtoui64(&expanded_size,
+ &line->data[8],
+ 0, APR_UINT64_MAX, 10);
+
+ if (err)
+ {
+ svn_error_clear(err);
+ break;
+ }
+
+ if (in_src)
+ {
+ bpatch->src_start = pos;
+ bpatch->src_filesize = expanded_size;
+ }
+ else
+ {
+ bpatch->dst_start = pos;
+ bpatch->dst_filesize = expanded_size;
+ }
+ in_blob = TRUE;
+ }
+ else
+ break; /* We don't support GIT deltas (yet) */
+ }
+ svn_pool_destroy(iterpool);
+
+ if (!eof)
+ /* Rewind to the start of the line just read, so subsequent calls
+ * don't end up skipping the line. It may contain a patch or hunk header.*/
+ SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &last_line, scratch_pool));
+ else if (in_src
+ && ((bpatch->src_end > bpatch->src_start) || !bpatch->src_filesize))
+ {
+ patch->binary_patch = bpatch; /* SUCCESS */
+ }
+
+ /* Reverse patch if requested */
+ if (reverse && patch->binary_patch)
+ {
+ apr_off_t tmp_start = bpatch->src_start;
+ apr_off_t tmp_end = bpatch->src_end;
+ svn_filesize_t tmp_filesize = bpatch->src_filesize;
+
+ bpatch->src_start = bpatch->dst_start;
+ bpatch->src_end = bpatch->dst_end;
+ bpatch->src_filesize = bpatch->dst_filesize;
+
+ bpatch->dst_start = tmp_start;
+ bpatch->dst_end = tmp_end;
+ bpatch->dst_filesize = tmp_filesize;
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* State machine for the diff header parser.
* Expected Input Required state Function to call */
static struct transition transitions[] =
{
- {"--- ", state_start, diff_minus},
- {"+++ ", state_minus_seen, diff_plus},
- {"diff --git", state_start, git_start},
- {"--- a/", state_git_diff_seen, git_minus},
- {"--- a/", state_git_tree_seen, git_minus},
- {"--- /dev/null", state_git_tree_seen, git_minus},
- {"+++ b/", state_git_minus_seen, git_plus},
- {"+++ /dev/null", state_git_minus_seen, git_plus},
- {"rename from ", state_git_diff_seen, git_move_from},
- {"rename to ", state_move_from_seen, git_move_to},
- {"copy from ", state_git_diff_seen, git_copy_from},
- {"copy to ", state_copy_from_seen, git_copy_to},
- {"new file ", state_git_diff_seen, git_new_file},
- {"deleted file ", state_git_diff_seen, git_deleted_file},
+ {"--- ", state_start, diff_minus},
+ {"+++ ", state_minus_seen, diff_plus},
+
+ {"diff --git", state_start, git_start},
+ {"--- a/", state_git_diff_seen, git_minus},
+ {"--- a/", state_git_mode_seen, git_minus},
+ {"--- a/", state_git_tree_seen, git_minus},
+ {"--- /dev/null", state_git_mode_seen, git_minus},
+ {"--- /dev/null", state_git_tree_seen, git_minus},
+ {"+++ b/", state_git_minus_seen, git_plus},
+ {"+++ /dev/null", state_git_minus_seen, git_plus},
+
+ {"old mode ", state_git_diff_seen, git_old_mode},
+ {"new mode ", state_old_mode_seen, git_new_mode},
+
+ {"rename from ", state_git_diff_seen, git_move_from},
+ {"rename from ", state_git_mode_seen, git_move_from},
+ {"rename to ", state_move_from_seen, git_move_to},
+
+ {"copy from ", state_git_diff_seen, git_copy_from},
+ {"copy from ", state_git_mode_seen, git_copy_from},
+ {"copy to ", state_copy_from_seen, git_copy_to},
+
+ {"new file ", state_git_diff_seen, git_new_file},
+
+ {"deleted file ", state_git_diff_seen, git_deleted_file},
+
+ {"index ", state_git_diff_seen, git_index},
+ {"index ", state_git_tree_seen, git_index},
+ {"index ", state_git_mode_seen, git_index},
+
+ {"GIT binary patch", state_git_diff_seen, binary_patch_start},
+ {"GIT binary patch", state_git_tree_seen, binary_patch_start},
+ {"GIT binary patch", state_git_mode_seen, binary_patch_start},
};
svn_error_t *
@@ -1389,6 +2133,10 @@ svn_diff_parse_next_patch(svn_patch_t **
}
patch = apr_pcalloc(result_pool, sizeof(*patch));
+ patch->old_executable_bit = svn_tristate_unknown;
+ patch->new_executable_bit = svn_tristate_unknown;
+ patch->old_symlink_bit = svn_tristate_unknown;
+ patch->new_symlink_bit = svn_tristate_unknown;
pos = patch_file->next_patch_offset;
SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &pos, scratch_pool));
@@ -1428,32 +2176,32 @@ svn_diff_parse_next_patch(svn_patch_t **
}
}
- if (state == state_unidiff_found || state == state_git_header_found)
+ if (state == state_unidiff_found
+ || state == state_git_header_found
+ || state == state_binary_patch_found)
{
/* We have a valid diff header, yay! */
break;
}
- else if (state == state_git_tree_seen && line_after_tree_header_read)
+ else if ((state == state_git_tree_seen || state == state_git_mode_seen)
+ && line_after_tree_header_read
+ && !valid_header_line)
{
- /* git patches can contain an index line after the file mode line */
- if (!starts_with(line->data, "index "))
- {
- /* We have a valid diff header for a patch with only tree changes.
- * Rewind to the start of the line just read, so subsequent calls
- * to this function don't end up skipping the line -- it may
- * contain a patch. */
- SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &last_line,
- scratch_pool));
- break;
- }
+ /* We have a valid diff header for a patch with only tree changes.
+ * Rewind to the start of the line just read, so subsequent calls
+ * to this function don't end up skipping the line -- it may
+ * contain a patch. */
+ SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &last_line,
+ scratch_pool));
+ break;
}
- else if (state == state_git_tree_seen)
+ else if (state == state_git_tree_seen
+ || state == state_git_mode_seen)
{
line_after_tree_header_read = TRUE;
}
else if (! valid_header_line && state != state_start
- && state != state_git_diff_seen
- && !starts_with(line->data, "index "))
+ && state != state_git_diff_seen)
{
/* We've encountered an invalid diff header.
*
@@ -1471,9 +2219,35 @@ svn_diff_parse_next_patch(svn_patch_t **
if (reverse)
{
const char *temp;
+ svn_tristate_t ts_tmp;
+
temp = patch->old_filename;
patch->old_filename = patch->new_filename;
patch->new_filename = temp;
+
+ switch (patch->operation)
+ {
+ case svn_diff_op_added:
+ patch->operation = svn_diff_op_deleted;
+ break;
+ case svn_diff_op_deleted:
+ patch->operation = svn_diff_op_added;
+ break;
+
+ /* ### case svn_diff_op_copied:
+ ### case svn_diff_op_moved:*/
+
+ case svn_diff_op_modified:
+ break; /* Stays modify */
+ }
+
+ ts_tmp = patch->old_executable_bit;
+ patch->old_executable_bit = patch->new_executable_bit;
+ patch->new_executable_bit = ts_tmp;
+
+ ts_tmp = patch->old_symlink_bit;
+ patch->old_symlink_bit = patch->new_symlink_bit;
+ patch->new_symlink_bit = ts_tmp;
}
if (patch->old_filename == NULL || patch->new_filename == NULL)
@@ -1482,8 +2256,17 @@ svn_diff_parse_next_patch(svn_patch_t **
patch = NULL;
}
else
- SVN_ERR(parse_hunks(patch, patch_file->apr_file, ignore_whitespace,
- result_pool, iterpool));
+ {
+ if (state == state_binary_patch_found)
+ {
+ SVN_ERR(parse_binary_patch(patch, patch_file->apr_file, reverse,
+ result_pool, iterpool));
+ /* And fall through in property parsing */
+ }
+
+ SVN_ERR(parse_hunks(patch, patch_file->apr_file, ignore_whitespace,
+ result_pool, iterpool));
+ }
svn_pool_destroy(iterpool);
@@ -1491,7 +2274,7 @@ svn_diff_parse_next_patch(svn_patch_t **
SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_CUR,
&patch_file->next_patch_offset, scratch_pool));
- if (patch)
+ if (patch && patch->hunks)
{
/* Usually, hunks appear in the patch sorted by their original line
* offset. But just in case they weren't parsed in this order for
Modified: subversion/branches/ra-git/subversion/libsvn_fs/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs/deprecated.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs/deprecated.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs/deprecated.c Mon Nov 30 10:24:16 2015
@@ -64,6 +64,28 @@ svn_fs_begin_txn(svn_fs_txn_t **txn_p, s
}
svn_error_t *
+svn_fs_revision_prop(svn_string_t **value_p,
+ svn_fs_t *fs,
+ svn_revnum_t rev,
+ const char *propname,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(
+ svn_fs_revision_prop2(value_p, fs, rev, propname, TRUE, pool,
+ pool));
+}
+
+svn_error_t *
+svn_fs_revision_proplist(apr_hash_t **table_p,
+ svn_fs_t *fs,
+ svn_revnum_t rev,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(
+ svn_fs_revision_proplist2(table_p, fs, rev, TRUE, pool, pool));
+}
+
+svn_error_t *
svn_fs_change_rev_prop(svn_fs_t *fs, svn_revnum_t rev, const char *name,
const svn_string_t *value, apr_pool_t *pool)
{
@@ -81,6 +103,55 @@ svn_fs_get_locks(svn_fs_t *fs, const cha
pool));
}
+svn_error_t *
+svn_fs_create(svn_fs_t **fs_p,
+ const char *path,
+ apr_hash_t *fs_config,
+ apr_pool_t *pool)
+{
+ return svn_fs_create2(fs_p, path, fs_config, pool, pool);
+}
+
+svn_error_t *
+svn_fs_open(svn_fs_t **fs_p,
+ const char *path,
+ apr_hash_t *fs_config,
+ apr_pool_t *pool)
+{
+ return svn_fs_open2(fs_p, path, fs_config, pool, pool);
+}
+
+svn_error_t *
+svn_fs_node_history(svn_fs_history_t **history_p, svn_fs_root_t *root,
+ const char *path, apr_pool_t *pool)
+{
+ return svn_error_trace(svn_fs_node_history2(history_p, root, path,
+ pool, pool));
+}
+
+svn_error_t *
+svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
+ svn_fs_root_t *root,
+ const apr_array_header_t *paths,
+ svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t include_descendants,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_fs_get_mergeinfo2(catalog, root, paths,
+ inherit,
+ include_descendants,
+ TRUE, pool, pool));
+}
+
+svn_error_t *
+svn_fs_history_prev(svn_fs_history_t **prev_history_p,
+ svn_fs_history_t *history, svn_boolean_t cross_copies,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_fs_history_prev2(prev_history_p, history,
+ cross_copies, pool, pool));
+}
+
/*** From access.c ***/
svn_error_t *
svn_fs_access_add_lock_token(svn_fs_access_t *access_ctx,
Modified: subversion/branches/ra-git/subversion/libsvn_fs/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs/editor.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs/editor.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs/editor.c Mon Nov 30 10:24:16 2015
@@ -249,7 +249,7 @@ can_modify(svn_fs_root_t *txn_root,
svn_fs_close_root(rev_root);
/* Has the target node changed in the future? */
- if (relation != svn_fs_node_same)
+ if (relation != svn_fs_node_unchanged)
{
/* Restarting the commit will base the txn on the future/new
revision, allowing the modification at REVISION. */
Modified: subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.c Mon Nov 30 10:24:16 2015
@@ -27,7 +27,6 @@
#include <apr_atomic.h>
#include <apr_hash.h>
#include <apr_md5.h>
-#include <apr_thread_mutex.h>
#include <apr_uuid.h>
#include <apr_strings.h>
@@ -140,7 +139,7 @@ load_module(fs_init_func_t *initfunc, co
_("Invalid name for FS type '%s'"),
name);
- libname = apr_psprintf(pool, "libsvn_fs_%s-%d.so.%d",
+ libname = apr_psprintf(pool, "libsvn_fs_%s-" SVN_DSO_SUFFIX_FMT,
name, SVN_VER_MAJOR, SVN_SOVERSION);
funcname = apr_psprintf(pool, "svn_fs_%s__init", name);
@@ -507,24 +506,28 @@ svn_fs_set_warning_func(svn_fs_t *fs, sv
}
svn_error_t *
-svn_fs_create(svn_fs_t **fs_p, const char *path, apr_hash_t *fs_config,
- apr_pool_t *pool)
+svn_fs_create2(svn_fs_t **fs_p,
+ const char *path,
+ apr_hash_t *fs_config,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_library_vtable_t *vtable;
const char *fs_type = svn_hash__get_cstring(fs_config,
SVN_FS_CONFIG_FS_TYPE,
DEFAULT_FS_TYPE);
- SVN_ERR(get_library_vtable(&vtable, fs_type, pool));
+ SVN_ERR(get_library_vtable(&vtable, fs_type, scratch_pool));
/* Create the FS directory and write out the fsap-name file. */
- SVN_ERR(svn_io_dir_make_sgid(path, APR_OS_DEFAULT, pool));
- SVN_ERR(write_fs_type(path, fs_type, pool));
+ SVN_ERR(svn_io_dir_make_sgid(path, APR_OS_DEFAULT, scratch_pool));
+ SVN_ERR(write_fs_type(path, fs_type, scratch_pool));
/* Perform the actual creation. */
- *fs_p = fs_new(fs_config, pool);
+ *fs_p = fs_new(fs_config, result_pool);
- SVN_ERR(vtable->create(*fs_p, path, common_pool_lock, pool, common_pool));
+ SVN_ERR(vtable->create(*fs_p, path, common_pool_lock, scratch_pool,
+ common_pool));
SVN_ERR(vtable->set_svn_fs_open(*fs_p, svn_fs_open2));
return SVN_NO_ERROR;
@@ -547,33 +550,24 @@ svn_fs_open2(svn_fs_t **fs_p, const char
}
svn_error_t *
-svn_fs_open(svn_fs_t **fs_p,
- const char *path,
- apr_hash_t *fs_config,
- apr_pool_t *pool)
-{
- return svn_fs_open2(fs_p, path, fs_config, pool, pool);
-}
-
-svn_error_t *
svn_fs_upgrade2(const char *path,
svn_fs_upgrade_notify_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
fs_library_vtable_t *vtable;
svn_fs_t *fs;
- SVN_ERR(fs_library_vtable(&vtable, path, pool));
- fs = fs_new(NULL, pool);
+ SVN_ERR(fs_library_vtable(&vtable, path, scratch_pool));
+ fs = fs_new(NULL, scratch_pool);
SVN_ERR(vtable->upgrade_fs(fs, path,
notify_func, notify_baton,
cancel_func, cancel_baton,
common_pool_lock,
- pool, common_pool));
+ scratch_pool, common_pool));
return SVN_NO_ERROR;
}
@@ -1101,14 +1095,6 @@ svn_fs_node_history2(svn_fs_history_t **
}
svn_error_t *
-svn_fs_node_history(svn_fs_history_t **history_p, svn_fs_root_t *root,
- const char *path, apr_pool_t *pool)
-{
- return svn_error_trace(root->vtable->node_history(history_p, root, path,
- pool, pool));
-}
-
-svn_error_t *
svn_fs_is_dir(svn_boolean_t *is_dir, svn_fs_root_t *root, const char *path,
apr_pool_t *pool)
{
@@ -1141,7 +1127,7 @@ svn_error_t *
svn_fs_node_relation(svn_fs_node_relation_t *relation,
svn_fs_root_t *root_a, const char *path_a,
svn_fs_root_t *root_b, const char *path_b,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
/* Different repository types? */
if (root_a->fs != root_b->fs)
@@ -1150,9 +1136,10 @@ svn_fs_node_relation(svn_fs_node_relatio
return SVN_NO_ERROR;
}
- return svn_error_trace(root_a->vtable->node_relation(relation, root_a,
- path_a, root_b,
- path_b, pool));
+ return svn_error_trace(root_a->vtable->node_relation(relation,
+ root_a, path_a,
+ root_b, path_b,
+ scratch_pool));
}
svn_error_t *
@@ -1196,6 +1183,16 @@ svn_fs_node_proplist(apr_hash_t **table_
}
svn_error_t *
+svn_fs_node_has_props(svn_boolean_t *has_props,
+ svn_fs_root_t *root,
+ const char *path,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(root->vtable->node_has_props(has_props, root, path,
+ scratch_pool));
+}
+
+svn_error_t *
svn_fs_change_node_prop(svn_fs_root_t *root, const char *path,
const char *name, const svn_string_t *value,
apr_pool_t *pool)
@@ -1207,12 +1204,12 @@ svn_fs_change_node_prop(svn_fs_root_t *r
svn_error_t *
svn_fs_props_different(svn_boolean_t *changed_p, svn_fs_root_t *root1,
const char *path1, svn_fs_root_t *root2,
- const char *path2, apr_pool_t *pool)
+ const char *path2, apr_pool_t *scratch_pool)
{
return svn_error_trace(root1->vtable->props_changed(changed_p,
root1, path1,
root2, path2,
- TRUE, pool));
+ TRUE, scratch_pool));
}
svn_error_t *
@@ -1258,20 +1255,6 @@ svn_fs_get_mergeinfo2(svn_mergeinfo_cata
}
svn_error_t *
-svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
- svn_fs_root_t *root,
- const apr_array_header_t *paths,
- svn_mergeinfo_inheritance_t inherit,
- svn_boolean_t include_descendants,
- apr_pool_t *pool)
-{
- return svn_error_trace(root->vtable->get_mergeinfo(catalog, root, paths,
- inherit,
- include_descendants,
- TRUE, pool, pool));
-}
-
-svn_error_t *
svn_fs__get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo,
svn_fs_root_t *root,
const char *path,
@@ -1320,10 +1303,13 @@ svn_error_t *
svn_fs_dir_optimal_order(apr_array_header_t **ordered_p,
svn_fs_root_t *root,
apr_hash_t *entries,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
return svn_error_trace(root->vtable->dir_optimal_order(ordered_p, root,
- entries, pool));
+ entries,
+ result_pool,
+ scratch_pool));
}
svn_error_t *
@@ -1484,12 +1470,13 @@ svn_fs_apply_text(svn_stream_t **content
svn_error_t *
svn_fs_contents_different(svn_boolean_t *changed_p, svn_fs_root_t *root1,
const char *path1, svn_fs_root_t *root2,
- const char *path2, apr_pool_t *pool)
+ const char *path2, apr_pool_t *scratch_pool)
{
return svn_error_trace(root1->vtable->contents_changed(changed_p,
root1, path1,
root2, path2,
- TRUE, pool));
+ TRUE,
+ scratch_pool));
}
svn_error_t *
@@ -1539,19 +1526,39 @@ svn_fs_deltify_revision(svn_fs_t *fs, sv
}
svn_error_t *
-svn_fs_revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev,
- const char *propname, apr_pool_t *pool)
+svn_fs_refresh_revision_props(svn_fs_t *fs,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(fs->vtable->refresh_revprops(fs, scratch_pool));
+}
+
+svn_error_t *
+svn_fs_revision_prop2(svn_string_t **value_p,
+ svn_fs_t *fs,
+ svn_revnum_t rev,
+ const char *propname,
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
return svn_error_trace(fs->vtable->revision_prop(value_p, fs, rev,
- propname, pool));
+ propname, refresh,
+ result_pool,
+ scratch_pool));
}
svn_error_t *
-svn_fs_revision_proplist(apr_hash_t **table_p, svn_fs_t *fs, svn_revnum_t rev,
- apr_pool_t *pool)
+svn_fs_revision_proplist2(apr_hash_t **table_p,
+ svn_fs_t *fs,
+ svn_revnum_t rev,
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
return svn_error_trace(fs->vtable->revision_proplist(table_p, fs, rev,
- pool));
+ refresh,
+ result_pool,
+ scratch_pool));
}
svn_error_t *
@@ -1757,9 +1764,9 @@ svn_fs_generate_lock_token(const char **
svn_fs_lock_target_t *
svn_fs_lock_target_create(const char *token,
svn_revnum_t current_rev,
- apr_pool_t *pool)
+ apr_pool_t *result_pool)
{
- svn_fs_lock_target_t *target = apr_palloc(pool, sizeof(svn_fs_lock_target_t));
+ svn_fs_lock_target_t *target = apr_palloc(result_pool, sizeof(*target));
target->token = token;
target->current_rev = current_rev;
@@ -1846,15 +1853,6 @@ svn_fs_history_prev2(svn_fs_history_t **
}
svn_error_t *
-svn_fs_history_prev(svn_fs_history_t **prev_history_p,
- svn_fs_history_t *history, svn_boolean_t cross_copies,
- apr_pool_t *pool)
-{
- return svn_error_trace(history->vtable->prev(prev_history_p, history,
- cross_copies, pool, pool));
-}
-
-svn_error_t *
svn_fs_history_location(const char **path, svn_revnum_t *revision,
svn_fs_history_t *history, apr_pool_t *pool)
{
@@ -1897,7 +1895,7 @@ svn_fs_compare_ids(const svn_fs_id_t *a,
{
switch (a->vtable->compare(a, b))
{
- case svn_fs_node_same:
+ case svn_fs_node_unchanged:
return 0;
case svn_fs_node_common_ancestor:
return 1;
Modified: subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.h?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs/fs-loader.h Mon Nov 30 10:24:16 2015
@@ -22,8 +22,8 @@
*/
-#ifndef LIBSVN_FS_FS_H
-#define LIBSVN_FS_FS_H
+#ifndef LIBSVN_FS_LOADER_H
+#define LIBSVN_FS_LOADER_H
#include "svn_types.h"
#include "svn_fs.h"
@@ -79,11 +79,11 @@ typedef struct fs_library_vtable_t
parameter for allocating fs-global objects such as an env cache. */
svn_error_t *(*create)(svn_fs_t *fs, const char *path,
svn_mutex__t *common_pool_lock,
- apr_pool_t *pool,
+ apr_pool_t *scratch_pool,
apr_pool_t *common_pool);
svn_error_t *(*open_fs)(svn_fs_t *fs, const char *path,
svn_mutex__t *common_pool_lock,
- apr_pool_t *pool,
+ apr_pool_t *scratch_pool,
apr_pool_t *common_pool);
/* open_for_recovery() is like open(), but used to fill in an fs pointer
that will be passed to recover(). We assume that the open() method
@@ -99,7 +99,7 @@ typedef struct fs_library_vtable_t
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_mutex__t *common_pool_lock,
- apr_pool_t *pool,
+ apr_pool_t *scratch_pool,
apr_pool_t *common_pool);
svn_error_t *(*verify_fs)(svn_fs_t *fs, const char *path,
svn_revnum_t start,
@@ -184,15 +184,9 @@ typedef svn_error_t *(*fs_init_func_t)(c
to the create and open functions and these init functions (as well
as the open and create functions) are globally serialized so that
they have exclusive access to the common_pool. */
-svn_error_t *svn_fs_base__init(const svn_version_t *loader_version,
- fs_library_vtable_t **vtable,
- apr_pool_t* common_pool);
-svn_error_t *svn_fs_fs__init(const svn_version_t *loader_version,
- fs_library_vtable_t **vtable,
- apr_pool_t* common_pool);
-svn_error_t *svn_fs_x__init(const svn_version_t *loader_version,
- fs_library_vtable_t **vtable,
- apr_pool_t* common_pool);
+#include "../libsvn_fs_base/fs_init.h"
+#include "../libsvn_fs_fs/fs_init.h"
+#include "../libsvn_fs_x/fs_init.h"
@@ -202,11 +196,17 @@ typedef struct fs_vtable_t
{
svn_error_t *(*youngest_rev)(svn_revnum_t *youngest_p, svn_fs_t *fs,
apr_pool_t *pool);
+ svn_error_t *(*refresh_revprops)(svn_fs_t *fs, apr_pool_t *scratch_pool);
svn_error_t *(*revision_prop)(svn_string_t **value_p, svn_fs_t *fs,
svn_revnum_t rev, const char *propname,
- apr_pool_t *pool);
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
svn_error_t *(*revision_proplist)(apr_hash_t **table_p, svn_fs_t *fs,
- svn_revnum_t rev, apr_pool_t *pool);
+ svn_revnum_t rev,
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
svn_error_t *(*change_rev_prop)(svn_fs_t *fs, svn_revnum_t rev,
const char *name,
const svn_string_t *const *old_value_p,
@@ -314,7 +314,7 @@ typedef struct root_vtable_t
svn_error_t *(*node_relation)(svn_fs_node_relation_t *relation,
svn_fs_root_t *root_a, const char *path_a,
svn_fs_root_t *root_b, const char *path_b,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
svn_error_t *(*node_created_rev)(svn_revnum_t *revision,
svn_fs_root_t *root, const char *path,
apr_pool_t *pool);
@@ -346,6 +346,8 @@ typedef struct root_vtable_t
apr_pool_t *pool);
svn_error_t *(*node_proplist)(apr_hash_t **table_p, svn_fs_root_t *root,
const char *path, apr_pool_t *pool);
+ svn_error_t *(*node_has_props)(svn_boolean_t *has_props, svn_fs_root_t *root,
+ const char *path, apr_pool_t *scratch_pool);
svn_error_t *(*change_node_prop)(svn_fs_root_t *root, const char *path,
const char *name,
const svn_string_t *value,
@@ -353,7 +355,7 @@ typedef struct root_vtable_t
svn_error_t *(*props_changed)(int *changed_p, svn_fs_root_t *root1,
const char *path1, svn_fs_root_t *root2,
const char *path2, svn_boolean_t strict,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
/* Directories */
svn_error_t *(*dir_entries)(apr_hash_t **entries_p, svn_fs_root_t *root,
@@ -361,7 +363,8 @@ typedef struct root_vtable_t
svn_error_t *(*dir_optimal_order)(apr_array_header_t **ordered_p,
svn_fs_root_t *root,
apr_hash_t *entries,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
svn_error_t *(*make_dir)(svn_fs_root_t *root, const char *path,
apr_pool_t *pool);
@@ -394,7 +397,7 @@ typedef struct root_vtable_t
svn_error_t *(*contents_changed)(int *changed_p, svn_fs_root_t *root1,
const char *path1, svn_fs_root_t *root2,
const char *path2, svn_boolean_t strict,
- apr_pool_t *pool);
+ apr_pool_t *scratch_pool);
svn_error_t *(*get_file_delta_stream)(svn_txdelta_stream_t **stream_p,
svn_fs_root_t *source_root,
const char *source_path,
@@ -566,4 +569,4 @@ struct svn_fs_lock_target_t
}
#endif /* __cplusplus */
-#endif
+#endif /* LIBSVN_FS_LOADER_H */
Modified: subversion/branches/ra-git/subversion/libsvn_fs_base/bdb/rev-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_base/bdb/rev-table.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_fs_base/bdb/rev-table.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_fs_base/bdb/rev-table.c Mon Nov 30 10:24:16 2015
@@ -79,6 +79,9 @@ svn_fs_bdb__get_rev(revision_t **revisio
numbers begin with one. */
db_recno_t recno = (db_recno_t) rev + 1;
+ if (!SVN_IS_VALID_REVNUM(rev))
+ return svn_fs_base__err_dangling_rev(fs, rev);
+
svn_fs_base__trail_debug(trail, "revisions", "get");
db_err = bfd->revisions->get(bfd->revisions, trail->db_txn,
svn_fs_base__set_dbt(&key, &recno,