📄 mucc.c
字号:
int i; for (i = 0; i < path_bits->nelts; ++i) { const char *path_bit = APR_ARRAY_IDX(path_bits, i, const char *); path_so_far = svn_path_join(path_so_far, path_bit, pool); operation = get_operation(path_so_far, operation, pool); if (! url) { /* Delete can operate on a copy, track it back to the source */ if (operation->operation == OP_REPLACE || operation->operation == OP_ADD) { copy_src = subtract_anchor(anchor, operation->url, pool); copy_rev = operation->rev; } else if (copy_src) copy_src = svn_path_join(copy_src, path_bit, pool); } } if (operation->operation != OP_OPEN && operation->operation != OP_DELETE) return svn_error_createf(SVN_ERR_BAD_URL, NULL, "unsupported multiple operations on '%s'", path); if (! url) { operation->operation = OP_DELETE; SVN_ERR(svn_ra_check_path(session, copy_src ? copy_src : path, copy_src ? copy_rev : head, &operation->kind, pool)); if (operation->kind == svn_node_none) { if (copy_src && strcmp(path, copy_src)) return svn_error_createf(SVN_ERR_BAD_URL, NULL, "'%s' (from '%s:%ld') not found", path, copy_src, copy_rev); else return svn_error_createf(SVN_ERR_BAD_URL, NULL, "'%s' not found", path); } } else { operation->operation = operation->operation == OP_DELETE ? OP_REPLACE : OP_ADD; SVN_ERR(svn_ra_check_path(session, subtract_anchor(anchor, url, pool), rev, &operation->kind, pool)); if (operation->kind == svn_node_none) return svn_error_createf(SVN_ERR_BAD_URL, NULL, "'%s' not found", url); operation->url = url; operation->rev = rev; } return SVN_NO_ERROR;}struct action { enum { ACTION_MV, ACTION_CP, ACTION_RM } action; svn_revnum_t rev; /* of url[0] for cp */ const char *url[2];};static svn_error_t *execute(const apr_array_header_t *actions, const char *anchor, const char *message, apr_pool_t *pool){ svn_ra_session_t *session; svn_revnum_t head; const svn_delta_editor_t *editor; void *editor_baton; struct operation root; svn_error_t *err; int i; SVN_ERR(svn_ra_open(&session, anchor, ra_callbacks(pool), NULL, NULL, pool)); SVN_ERR(svn_ra_get_latest_revnum(session, &head, pool)); root.children = apr_hash_make(pool); root.operation = OP_OPEN; for (i = 0; i < actions->nelts; ++i) { struct action *action = APR_ARRAY_IDX(actions, i, struct action *); switch (action->action) { const char *path1, *path2; case ACTION_MV: path1 = subtract_anchor(anchor, action->url[0], pool); path2 = subtract_anchor(anchor, action->url[1], pool); SVN_ERR(build(path2, action->url[0], head, head, anchor, session, &root, pool)); SVN_ERR(build(path1, NULL, SVN_INVALID_REVNUM, head, anchor, session, &root, pool)); break; case ACTION_CP: path1 = subtract_anchor(anchor, action->url[0], pool); path2 = subtract_anchor(anchor, action->url[1], pool); if (action->rev == SVN_INVALID_REVNUM) action->rev = head; SVN_ERR(build(path2, action->url[0], action->rev, head, anchor, session, &root, pool)); break; case ACTION_RM: path1 = subtract_anchor(anchor, action->url[0], pool); SVN_ERR(build(path1, NULL, SVN_INVALID_REVNUM, head, anchor, session, &root, pool)); break; } } SVN_ERR(svn_ra_get_commit_editor(session, &editor, &editor_baton, message, commit_callback, pool, NULL, FALSE, pool)); SVN_ERR(editor->open_root(editor_baton, head, pool, &root.baton)); err = drive(&root, head, editor, pool); if (!err) err = editor->close_edit(editor_baton, pool); if (err) svn_error_clear(editor->abort_edit(editor_baton, pool)); return err;}static voidusage(apr_pool_t *pool, int exit_val){ FILE *stream = exit_val == EXIT_SUCCESS ? stdout : stderr; const char msg[] = "usage: mucc [OPTION]... [ mv URL1 URL2 | cp REV URL1 URL2 | rm URL ]...\n" "options:\n" " -m, --message ARG use ARG as a log message\n" " -F, --file ARG read log message from file ARG\n" " -h, --help display this text\n"; svn_error_clear(svn_cmdline_fputs(msg, stream, pool)); apr_pool_destroy(pool); exit(exit_val);}static voidinsufficient(apr_pool_t *pool){ handle_error(svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, "insufficient arguments"), pool);}intmain(int argc, const char **argv){ apr_pool_t *pool = init("mucc"); apr_array_header_t *actions = apr_array_make(pool, 1, sizeof(struct action*)); const char *anchor = NULL; svn_error_t *err; apr_getopt_t *getopt; const apr_getopt_option_t options[] = { {"message", 'm', 1, ""}, {"file", 'F', 1, ""}, {"help", 'h', 0, ""}, {NULL, 0, 0, NULL} }; const char *message = "committed using mucc"; apr_getopt_init(&getopt, pool, argc, argv); getopt->interleave = 1; while (1) { int opt; const char *arg; apr_status_t status = apr_getopt_long(getopt, options, &opt, &arg); if (APR_STATUS_IS_EOF(status)) break; if (status != APR_SUCCESS) handle_error(svn_error_wrap_apr(status, "getopt failure"), pool); switch(opt) { case 'm': err = svn_utf_cstring_to_utf8(&message, arg, pool); if (err) handle_error(err, pool); break; case 'F': { const char *arg_utf8; svn_stringbuf_t *contents; err = svn_utf_cstring_to_utf8(&arg_utf8, arg, pool); if (! err) err = svn_stringbuf_from_file(&contents, arg, pool); if (! err) err = svn_utf_cstring_to_utf8(&message, contents->data, pool); if (err) handle_error(err, pool); } break; case 'h': usage(pool, EXIT_SUCCESS); } } while (getopt->ind < getopt->argc) { int j; struct action *action = apr_palloc(pool, sizeof(*action)); if (! strcmp(getopt->argv[getopt->ind], "mv")) action->action = ACTION_MV; else if (! strcmp(getopt->argv[getopt->ind], "cp")) action->action = ACTION_CP; else if (! strcmp(getopt->argv[getopt->ind], "rm")) action->action = ACTION_RM; else handle_error(svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, "'%s' is not an action\n", getopt->argv[getopt->ind]), pool); if (++getopt->ind == getopt->argc) insufficient(pool); if (action->action == ACTION_CP) { if (! strcmp(getopt->argv[getopt->ind], "head")) action->rev = SVN_INVALID_REVNUM; else { char *end; action->rev = strtol(getopt->argv[getopt->ind], &end, 0); if (*end) handle_error(svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, "'%s' is not a revision\n", getopt->argv[getopt->ind]), pool); } if (++getopt->ind == getopt->argc) insufficient(pool); } else action->rev = SVN_INVALID_REVNUM; for (j = 0; j < (action->action == ACTION_RM ? 1 : 2); ++j) { const char *url = getopt->argv[getopt->ind]; err = svn_utf_cstring_to_utf8(&url, url, pool); if (err) handle_error(err, pool); if (! svn_path_is_url(url)) handle_error(svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, "'%s' is not an URL\n", getopt->argv[getopt->ind]), pool); url = svn_path_uri_from_iri(url, pool); url = svn_path_uri_autoescape(url, pool); url = svn_path_canonicalize(url, pool); action->url[j] = url; /* The cp source could be the anchor, but the other URLs should be children of the anchor. */ if (! (action->action == ACTION_CP && j == 0)) url = svn_path_dirname(url, pool); if (! anchor) anchor = url; else anchor = svn_path_get_longest_ancestor(anchor, url, pool); if (++getopt->ind == getopt->argc && ! (j == 1 || action->action == ACTION_RM)) insufficient(pool); } APR_ARRAY_PUSH(actions, struct action *) = action; } if (! actions->nelts) usage(pool, EXIT_FAILURE); err = execute(actions, anchor, message, pool); if (err) handle_error(err, pool); svn_pool_destroy(pool); return EXIT_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -