📄 main.c
字号:
|| (tmp_node->action == 'D')) { print_me = 1; } while (tmp_node->sibling && (! print_me )) { tmp_node = tmp_node->sibling; if ((tmp_node->kind == svn_node_file) || (tmp_node->text_mod) || (tmp_node->action == 'A') || (tmp_node->action == 'D')) { print_me = 1; } } } } /* Print the node if it qualifies. */ if (print_me) { SVN_ERR(svn_cmdline_printf(pool, "%s/\n", path)); } /* Return here if the node has no children. */ tmp_node = node->child; if (! tmp_node) return SVN_NO_ERROR; /* Recursively handle the node's children. */ subpool = svn_pool_create(pool); full_path = svn_path_join(path, tmp_node->name, subpool); SVN_ERR(print_dirs_changed_tree(tmp_node, full_path, subpool)); while (tmp_node->sibling) { svn_pool_clear(subpool); tmp_node = tmp_node->sibling; full_path = svn_path_join(path, tmp_node->name, subpool); SVN_ERR(print_dirs_changed_tree(tmp_node, full_path, subpool)); } svn_pool_destroy(subpool); return SVN_NO_ERROR;}/* Recursively print all nodes in the tree that have been modified (do not include directories affected only by "bubble-up"). */static svn_error_t *print_changed_tree(svn_repos_node_t *node, const char *path /* UTF-8! */, svn_boolean_t copy_info, apr_pool_t *pool){ const char *full_path; char status[4] = "_ "; int print_me = 1; apr_pool_t *subpool; SVN_ERR(check_cancel(NULL)); if (! node) return SVN_NO_ERROR; /* Print the node. */ if (node->action == 'A') { status[0] = 'A'; if (copy_info && node->copyfrom_path) status[2] = '+'; } else if (node->action == 'D') status[0] = 'D'; else if (node->action == 'R') { if ((! node->text_mod) && (! node->prop_mod)) print_me = 0; if (node->text_mod) status[0] = 'U'; if (node->prop_mod) status[1] = 'U'; } else print_me = 0; /* Print this node unless told to skip it. */ if (print_me) { SVN_ERR(svn_cmdline_printf(pool, "%s %s%s\n", status, path, node->kind == svn_node_dir ? "/" : "")); if (copy_info && node->copyfrom_path) /* Remove the leading slash from the copyfrom path for consistency with the rest of the output. */ SVN_ERR(svn_cmdline_printf(pool, " (from %s%s:r%ld)\n", (node->copyfrom_path[0] == '/' ? node->copyfrom_path + 1 : node->copyfrom_path), (node->kind == svn_node_dir ? "/" : ""), node->copyfrom_rev)); } /* Return here if the node has no children. */ node = node->child; if (! node) return SVN_NO_ERROR; /* Recursively handle the node's children. */ subpool = svn_pool_create(pool); full_path = svn_path_join(path, node->name, subpool); SVN_ERR(print_changed_tree(node, full_path, copy_info, subpool)); while (node->sibling) { svn_pool_clear(subpool); node = node->sibling; full_path = svn_path_join(path, node->name, subpool); SVN_ERR(print_changed_tree(node, full_path, copy_info, subpool)); } svn_pool_destroy(subpool); return SVN_NO_ERROR;}static svn_error_t *dump_contents(apr_file_t *fh, svn_fs_root_t *root, const char *path /* UTF-8! */, apr_pool_t *pool){ svn_stream_t *contents, *file_stream; /* Grab the contents and copy them into fh. */ SVN_ERR(svn_fs_file_contents(&contents, root, path, pool)); file_stream = svn_stream_from_aprfile(fh, pool); SVN_ERR(svn_stream_copy(contents, file_stream, pool)); return SVN_NO_ERROR;}/* Prepare temporary files *TMPFILE1 and *TMPFILE2 for diffing PATH1@ROOT1 versus PATH2@ROOT2. If either ROOT1 or ROOT2 is NULL, the temporary file for its path/root will be an empty one. Otherwise, its temporary file will contain the contents of that path/root in the repository. An exception to this is when either path/root has an svn:mime-type property set on it which indicates that the file contains non-textual data -- in this case, the *IS_BINARY flag is set and no temporary files are created. Use POOL for all that allocation goodness. */static svn_error_t *prepare_tmpfiles(const char **tmpfile1, const char **tmpfile2, svn_boolean_t *is_binary, svn_fs_root_t *root1, const char *path1, svn_fs_root_t *root2, const char *path2, const char *tmpdir, apr_pool_t *pool){ svn_string_t *mimetype; apr_file_t *fh; /* Init the return values. */ *tmpfile1 = NULL; *tmpfile2 = NULL; *is_binary = FALSE; assert(path1 && path2); /* Check for binary mimetypes. If either file has a binary mimetype, get outta here. */ if (root1) { SVN_ERR(svn_fs_node_prop(&mimetype, root1, path1, SVN_PROP_MIME_TYPE, pool)); if (mimetype && svn_mime_type_is_binary(mimetype->data)) { *is_binary = TRUE; return SVN_NO_ERROR; } } if (root2) { SVN_ERR(svn_fs_node_prop(&mimetype, root2, path2, SVN_PROP_MIME_TYPE, pool)); if (mimetype && svn_mime_type_is_binary(mimetype->data)) { *is_binary = TRUE; return SVN_NO_ERROR; } } /* Now, prepare the two temporary files, each of which will either be empty, or will have real contents. */ SVN_ERR(svn_io_open_unique_file2(&fh, tmpfile2, apr_psprintf(pool, "%s/diff", tmpdir), ".tmp", svn_io_file_del_none, pool)); if (root2) SVN_ERR(dump_contents(fh, root2, path2, pool)); apr_file_close(fh); /* The second file is constructed from the first one's path. */ SVN_ERR(svn_io_open_unique_file2(&fh, tmpfile1, *tmpfile2, ".tmp", svn_io_file_del_none, pool)); if (root1) SVN_ERR(dump_contents(fh, root1, path1, pool)); apr_file_close(fh); return SVN_NO_ERROR;}/* Generate a diff label for PATH in ROOT, allocating in POOL. ROOT may be NULL, in which case revision 0 is used. */static svn_error_t *generate_label(const char **label, svn_fs_root_t *root, const char *path, apr_pool_t *pool){ svn_string_t *date; const char *datestr; const char *name = NULL; svn_revnum_t rev = SVN_INVALID_REVNUM; if (root) { svn_fs_t *fs = svn_fs_root_fs(root); if (svn_fs_is_revision_root(root)) { rev = svn_fs_revision_root_revision(root); SVN_ERR(svn_fs_revision_prop(&date, fs, rev, SVN_PROP_REVISION_DATE, pool)); } else { svn_fs_txn_t *txn; name = svn_fs_txn_root_name(root, pool); SVN_ERR(svn_fs_open_txn(&txn, fs, name, pool)); SVN_ERR(svn_fs_txn_prop(&date, txn, SVN_PROP_REVISION_DATE, pool)); } } else { rev = 0; date = NULL; } if (date) datestr = apr_psprintf(pool, "%.10s %.8s UTC", date->data, date->data + 11); else datestr = " "; if (name) *label = apr_psprintf(pool, "%s\t%s (txn %s)", path, datestr, name); else *label = apr_psprintf(pool, "%s\t%s (rev %ld)", path, datestr, rev); return SVN_NO_ERROR;}/* * Constant diff output separator strings */static const char equal_string[] = "===================================================================";static const char under_string[] = "___________________________________________________________________";/* Helper function to display differences in properties of a file */static svn_error_t *display_prop_diffs(const apr_array_header_t *prop_diffs, apr_hash_t *orig_props, const char *path, apr_pool_t *pool){ int i; SVN_ERR(svn_cmdline_printf(pool, "\nProperty changes on: %s\n%s\n", path, under_string)); for (i = 0; i < prop_diffs->nelts; i++) { const svn_string_t *orig_value; const svn_prop_t *pc = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t); SVN_ERR(check_cancel(NULL)); if (orig_props) orig_value = apr_hash_get(orig_props, pc->name, APR_HASH_KEY_STRING); else orig_value = NULL; SVN_ERR(svn_cmdline_printf(pool, _("Name: %s\n"), pc->name)); /* For now, we have a rather simple heuristic: if this is an "svn:" property, then assume the value is UTF-8 and must therefore be converted before printing. Otherwise, just print whatever's there and hope for the best. ### We don't use svn_cmdline_printf here, since we don't know if the values are UTF-8. */ { svn_boolean_t val_to_utf8 = svn_prop_is_svn_prop(pc->name); const char *printable_val; if (orig_value != NULL) { if (val_to_utf8) SVN_ERR(svn_cmdline_cstring_from_utf8(&printable_val, orig_value->data, pool)); else printable_val = orig_value->data; printf(" - %s\n", printable_val); } if (pc->value != NULL) { if (val_to_utf8) SVN_ERR(svn_cmdline_cstring_from_utf8 (&printable_val, pc->value->data, pool)); else printable_val = pc->value->data; printf(" + %s\n", printable_val); } } } SVN_ERR(svn_cmdline_printf(pool, "\n")); return svn_cmdline_fflush(stdout);}/* Recursively print all nodes in the tree that have been modified (do not include directories affected only by "bubble-up"). */static svn_error_t *print_diff_tree(svn_fs_root_t *root, svn_fs_root_t *base_root, svn_repos_node_t *node, const char *path /* UTF-8! */, const char *base_path /* UTF-8! */, const svnlook_ctxt_t *c, const char *tmpdir, apr_pool_t *pool){ const char *orig_path = NULL, *new_path = NULL; svn_boolean_t do_diff = FALSE; svn_boolean_t orig_empty = FALSE; svn_boolean_t is_copy = FALSE; svn_boolean_t printed_header = FALSE; svn_boolean_t binary = FALSE; apr_pool_t *subpool; SVN_ERR(check_cancel(NULL)); if (! node) return SVN_NO_ERROR; /* Print copyfrom history for the top node of a copied tree. */ if ((SVN_IS_VALID_REVNUM(node->copyfrom_rev)) && (node->copyfrom_path != NULL)) { /* This is ... a copy. */ is_copy = TRUE; /* Propagate the new base. Copyfrom paths usually start with a slash; we remove it for consistency with the target path. ### Yes, it would be *much* better for something in the path library to be taking care of this! */ if (node->copyfrom_path[0] == '/') base_path = apr_pstrdup(pool, node->copyfrom_path + 1); else base_path = apr_pstrdup(pool, node->copyfrom_path); SVN_ERR(svn_cmdline_printf(pool, _("Copied: %s (from rev %ld, %s)\n"), path, node->copyfrom_rev, base_path)); printed_header = TRUE; SVN_ERR(svn_fs_revision_root(&base_root, svn_fs_root_fs(base_root), node->copyfrom_rev, pool)); } /*** First, we'll just print file content diffs. ***/ if (node->kind == svn_node_file) { /* Here's the generalized way we do our diffs: - First, we'll check for svn:mime-type properties on the old and new files. If either has such a property, and it represents a binary type, we won't actually be doing a real diff. - Second, dump the contents of the new version of the file into the temporary directory. - Then, dump the contents of the old version of the file into the temporary directory. - Next, we run 'diff', passing the repository paths as the labels. - Finally, we delete the temporary files. */ if (node->action == 'R' && node->text_mod) { do_diff = TRUE; SVN_ERR(prepare_tmpfiles(&orig_path, &new_path, &binary, base_root, base_path, root, path, tmpdir, pool)); } else if (c->diff_copy_from && node->action == 'A' && is_copy) { if (node->text_mod) { do_diff = TRUE; SVN_ERR(prepare_tmpfiles(&orig_path, &new_path, &binary, base_root, base_path, root, path, tmpdir, pool)); } } else if (! c->no_diff_added && node->action == 'A') { do_diff = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -