📄 diff3.c
字号:
/* * diff3.c : routines for doing diffs * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <apr.h>#include <apr_pools.h>#include <apr_general.h>#include "svn_pools.h"#include "svn_error.h"#include "svn_diff.h"#include "svn_types.h"#include "diff.h"voidsvn_diff__resolve_conflict(svn_diff_t *hunk, svn_diff__position_t **position_list1, svn_diff__position_t **position_list2, apr_pool_t *pool){ apr_off_t modified_start = hunk->modified_start + 1; apr_off_t latest_start = hunk->latest_start + 1; apr_off_t common_length; apr_off_t modified_length = hunk->modified_length; apr_off_t latest_length = hunk->latest_length; svn_diff__position_t *start_position[2]; svn_diff__position_t *position[2]; svn_diff__lcs_t *lcs = NULL; svn_diff__lcs_t **lcs_ref = &lcs; svn_diff_t **diff_ref = &hunk->resolved_diff; apr_pool_t *subpool; /* First find the starting positions for the * comparison */ start_position[0] = *position_list1; start_position[1] = *position_list2; while (start_position[0]->offset < modified_start) start_position[0] = start_position[0]->next; while (start_position[1]->offset < latest_start) start_position[1] = start_position[1]->next; position[0] = start_position[0]; position[1] = start_position[1]; common_length = modified_length < latest_length ? modified_length : latest_length; while (common_length > 0 && position[0]->node == position[1]->node) { position[0] = position[0]->next; position[1] = position[1]->next; common_length--; } if (common_length == 0 && modified_length == latest_length) { hunk->type = svn_diff__type_diff_common; hunk->resolved_diff = NULL; *position_list1 = position[0]; *position_list2 = position[1]; return; } hunk->type = svn_diff__type_conflict; /* ### If we have a conflict we can try to find the * ### common parts in it by getting an lcs between * ### modified (start to start + length) and * ### latest (start to start + length). * ### We use this lcs to create a simple diff. Only * ### where there is a diff between the two, we have * ### a conflict. * ### This raises a problem; several common diffs and * ### conflicts can occur within the same original * ### block. This needs some thought. * ### * ### NB: We can use the node _pointers_ to identify * ### different tokens */ subpool = svn_pool_create(pool); /* Calculate how much of the two sequences was * actually the same. */ common_length = (modified_length < latest_length ? modified_length : latest_length) - common_length; /* If there were matching symbols at the start of * both sequences, record that fact. */ if (common_length > 0) { lcs = apr_palloc(subpool, sizeof(*lcs)); lcs->next = NULL; lcs->position[0] = start_position[0]; lcs->position[1] = start_position[1]; lcs->length = common_length; lcs_ref = &lcs->next; } modified_length -= common_length; latest_length -= common_length; modified_start = start_position[0]->offset; latest_start = start_position[1]->offset; start_position[0] = position[0]; start_position[1] = position[1]; /* Create a new ring for svn_diff__lcs to grok. * We can safely do this given we don't need the * positions we processed anymore. */ if (modified_length == 0) { *position_list1 = position[0]; position[0] = NULL; } else { while (--modified_length) position[0] = position[0]->next; *position_list1 = position[0]->next; position[0]->next = start_position[0]; } if (latest_length == 0) { *position_list2 = position[1]; position[1] = NULL; } else { while (--latest_length) position[1] = position[1]->next; *position_list2 = position[1]->next; position[1]->next = start_position[1]; } *lcs_ref = svn_diff__lcs(position[0], position[1], subpool); /* Fix up the EOF lcs element in case one of * the two sequences was NULL. */ if ((*lcs_ref)->position[0]->offset == 1) (*lcs_ref)->position[0] = *position_list1; if ((*lcs_ref)->position[1]->offset == 1) (*lcs_ref)->position[1] = *position_list2; /* Restore modified_length and latest_length */ modified_length = hunk->modified_length; latest_length = hunk->latest_length; /* Produce the resolved diff */ while (1) { if (modified_start < lcs->position[0]->offset || latest_start < lcs->position[1]->offset) { (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref)); (*diff_ref)->type = svn_diff__type_conflict; (*diff_ref)->original_start = hunk->original_start; (*diff_ref)->original_length = hunk->original_length; (*diff_ref)->modified_start = modified_start - 1; (*diff_ref)->modified_length = lcs->position[0]->offset - modified_start; (*diff_ref)->latest_start = latest_start - 1; (*diff_ref)->latest_length = lcs->position[1]->offset - latest_start; (*diff_ref)->resolved_diff = NULL; diff_ref = &(*diff_ref)->next; } /* Detect the EOF */ if (lcs->length == 0) break; modified_start = lcs->position[0]->offset; latest_start = lcs->position[1]->offset; (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref)); (*diff_ref)->type = svn_diff__type_diff_common; (*diff_ref)->original_start = hunk->original_start; (*diff_ref)->original_length = hunk->original_length; (*diff_ref)->modified_start = modified_start - 1; (*diff_ref)->modified_length = lcs->length; (*diff_ref)->latest_start = latest_start - 1; (*diff_ref)->latest_length = lcs->length; (*diff_ref)->resolved_diff = NULL; diff_ref = &(*diff_ref)->next; modified_start += lcs->length; latest_start += lcs->length; lcs = lcs->next; } *diff_ref = NULL; svn_pool_destroy(subpool);}svn_error_t *svn_diff_diff3(svn_diff_t **diff, void *diff_baton, const svn_diff_fns_t *vtable, apr_pool_t *pool){ svn_diff__tree_t *tree; svn_diff__position_t *position_list[3]; svn_diff__lcs_t *lcs_om; svn_diff__lcs_t *lcs_ol;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -