📄 diff3.c
字号:
apr_pool_t *subpool;
apr_pool_t *treepool;
*diff = NULL;
subpool = svn_pool_create(pool);
treepool = svn_pool_create(pool);
svn_diff__tree_create(&tree, treepool);
SVN_ERR(svn_diff__get_tokens(&position_list[0],
tree,
diff_baton, vtable,
svn_diff_datasource_original,
subpool));
SVN_ERR(svn_diff__get_tokens(&position_list[1],
tree,
diff_baton, vtable,
svn_diff_datasource_modified,
subpool));
SVN_ERR(svn_diff__get_tokens(&position_list[2],
tree,
diff_baton, vtable,
svn_diff_datasource_latest,
subpool));
/* Get rid of the tokens, we don't need them to calc the diff */
if (vtable->token_discard_all != NULL)
vtable->token_discard_all(diff_baton);
/* We don't need the nodes in the tree either anymore, nor the tree itself */
svn_pool_destroy(treepool);
/* Get the lcs for original-modified and original-latest */
lcs_om = svn_diff__lcs(position_list[0], position_list[1],
subpool);
lcs_ol = svn_diff__lcs(position_list[0], position_list[2],
subpool);
/* Produce a merged diff */
{
svn_diff_t **diff_ref = diff;
apr_off_t original_start = 1;
apr_off_t modified_start = 1;
apr_off_t latest_start = 1;
apr_off_t original_sync;
apr_off_t modified_sync;
apr_off_t latest_sync;
apr_off_t common_length;
apr_off_t original_length;
apr_off_t modified_length;
apr_off_t latest_length;
svn_boolean_t is_modified;
svn_boolean_t is_latest;
svn_diff__position_t sentinel_position[2];
/* Point the position lists to the start of the list
* so that common_diff/conflict detection actually is
* able to work.
*/
if (position_list[1])
{
sentinel_position[0].next = position_list[1]->next;
sentinel_position[0].offset = position_list[1]->offset + 1;
position_list[1]->next = &sentinel_position[0];
position_list[1] = sentinel_position[0].next;
}
else
{
sentinel_position[0].offset = 1;
sentinel_position[0].next = NULL;
position_list[1] = &sentinel_position[0];
}
if (position_list[2])
{
sentinel_position[1].next = position_list[2]->next;
sentinel_position[1].offset = position_list[2]->offset + 1;
position_list[2]->next = &sentinel_position[1];
position_list[2] = sentinel_position[1].next;
}
else
{
sentinel_position[1].offset = 1;
sentinel_position[1].next = NULL;
position_list[2] = &sentinel_position[1];
}
while (1)
{
/* Find the sync points */
while (1)
{
if (lcs_om->position[0]->offset > lcs_ol->position[0]->offset)
{
original_sync = lcs_om->position[0]->offset;
while (lcs_ol->position[0]->offset + lcs_ol->length
< original_sync)
lcs_ol = lcs_ol->next;
/* If the sync point is the EOF, and our current lcs segment
* doesn't reach as far as EOF, we need to skip this segment.
*/
if (lcs_om->length == 0 && lcs_ol->length > 0
&& lcs_ol->position[0]->offset + lcs_ol->length
== original_sync
&& lcs_ol->position[1]->offset + lcs_ol->length
!= lcs_ol->next->position[1]->offset)
lcs_ol = lcs_ol->next;
if (lcs_ol->position[0]->offset <= original_sync)
break;
}
else
{
original_sync = lcs_ol->position[0]->offset;
while (lcs_om->position[0]->offset + lcs_om->length
< original_sync)
lcs_om = lcs_om->next;
/* If the sync point is the EOF, and our current lcs segment
* doesn't reach as far as EOF, we need to skip this segment.
*/
if (lcs_ol->length == 0 && lcs_om->length > 0
&& lcs_om->position[0]->offset + lcs_om->length
== original_sync
&& lcs_om->position[1]->offset + lcs_om->length
!= lcs_om->next->position[1]->offset)
lcs_om = lcs_om->next;
if (lcs_om->position[0]->offset <= original_sync)
break;
}
}
modified_sync = lcs_om->position[1]->offset
+ (original_sync - lcs_om->position[0]->offset);
latest_sync = lcs_ol->position[1]->offset
+ (original_sync - lcs_ol->position[0]->offset);
/* Determine what is modified, if anything */
is_modified = lcs_om->position[0]->offset - original_start > 0
|| lcs_om->position[1]->offset - modified_start > 0;
is_latest = lcs_ol->position[0]->offset - original_start > 0
|| lcs_ol->position[1]->offset - latest_start > 0;
if (is_modified || is_latest)
{
original_length = original_sync - original_start;
modified_length = modified_sync - modified_start;
latest_length = latest_sync - latest_start;
(*diff_ref) = apr_palloc(pool, sizeof(**diff_ref));
(*diff_ref)->original_start = original_start - 1;
(*diff_ref)->original_length = original_sync - original_start;
(*diff_ref)->modified_start = modified_start - 1;
(*diff_ref)->modified_length = modified_length;
(*diff_ref)->latest_start = latest_start - 1;
(*diff_ref)->latest_length = latest_length;
(*diff_ref)->resolved_diff = NULL;
if (is_modified && is_latest)
{
svn_diff__resolve_conflict(*diff_ref,
&position_list[1],
&position_list[2],
pool);
}
else if (is_modified)
{
(*diff_ref)->type = svn_diff__type_diff_modified;
}
else
{
(*diff_ref)->type = svn_diff__type_diff_latest;
}
diff_ref = &(*diff_ref)->next;
}
/* Detect EOF */
if (lcs_om->length == 0 || lcs_ol->length == 0)
break;
modified_length = lcs_om->length
- (original_sync - lcs_om->position[0]->offset);
latest_length = lcs_ol->length
- (original_sync - lcs_ol->position[0]->offset);
common_length = modified_length < latest_length
? modified_length : latest_length;
(*diff_ref) = apr_palloc(pool, sizeof(**diff_ref));
(*diff_ref)->type = svn_diff__type_common;
(*diff_ref)->original_start = original_sync - 1;
(*diff_ref)->original_length = common_length;
(*diff_ref)->modified_start = modified_sync - 1;
(*diff_ref)->modified_length = common_length;
(*diff_ref)->latest_start = latest_sync - 1;
(*diff_ref)->latest_length = common_length;
(*diff_ref)->resolved_diff = NULL;
diff_ref = &(*diff_ref)->next;
/* Set the new offsets */
original_start = original_sync + common_length;
modified_start = modified_sync + common_length;
latest_start = latest_sync + common_length;
/* Make it easier for diff_common/conflict detection
by recording last lcs start positions
*/
if (position_list[1]->offset < lcs_om->position[1]->offset)
position_list[1] = lcs_om->position[1];
if (position_list[2]->offset < lcs_ol->position[1]->offset)
position_list[2] = lcs_ol->position[1];
/* Make sure we are pointing to lcs entries beyond
* the range we just processed
*/
while (original_start >= lcs_om->position[0]->offset + lcs_om->length
&& lcs_om->length > 0)
{
lcs_om = lcs_om->next;
}
while (original_start >= lcs_ol->position[0]->offset + lcs_ol->length
&& lcs_ol->length > 0)
{
lcs_ol = lcs_ol->next;
}
}
*diff_ref = NULL;
}
svn_pool_destroy(subpool);
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -