diff -Naur patchtool-0.5/cmd.h patchtool-0.6/cmd.h --- patchtool-0.5/cmd.h 2005-04-10 23:50:51.000000000 +0000 +++ patchtool-0.6/cmd.h 2005-04-16 18:17:05.000000000 +0000 @@ -20,6 +20,8 @@ "list [-d ] PATCHFILE", "sparse PATCHFILE dir", "get PATCHFILE part", + "modify PATCHFILE [--copy a b|--move a b|--remove a b] ...", + "version", NULL }; @@ -33,6 +35,8 @@ fprintf(stderr, " list List modified files from a patch\n"); fprintf(stderr, " sparse Sparse a patch with a directory layout\n"); fprintf(stderr, " get Get a part of a patch\n"); + fprintf(stderr, " modify reorganize a patch\n"); + fprintf(stderr, " version tool's version\n"); fprintf(stderr, "\n"); } else for (i = 0; i < sizeof(cmd_usage); i++) @@ -48,5 +52,7 @@ int cmd_list(int argc, char **argv); int cmd_get(int argc, char **argv); int cmd_sparse(int argc, char **argv); +int cmd_modify(int argc, char **argv); +int cmd_version(int argc, char **argv); #endif /* !_CMD_H */ diff -Naur patchtool-0.5/cmd_modify.c patchtool-0.6/cmd_modify.c --- patchtool-0.5/cmd_modify.c 1970-01-01 00:00:00.000000000 +0000 +++ patchtool-0.6/cmd_modify.c 2005-04-16 22:30:32.000000000 +0000 @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2005 Vincent Hanquez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include "patch.h" +#include "cmd.h" + +typedef enum { CMD_NO = 0, CMD_MOV = 1, CMD_CPY, CMD_DEL, } cmd_t; + +struct rule +{ + cmd_t cmd; + char *argv[2]; +}; + +#define MAX_RULES 64 + +int parse_rule(int argc, char **argv, struct rule *rule) +{ + cmd_t cmd; + char *c; + int nb_arg, i; + + c = argv[0] + 2; + if (strcmp(c, "copy") == 0 || strcmp(c, "cp") == 0) { + cmd = CMD_CPY; + nb_arg = 2; + } else if (strcmp(c, "move") == 0 || strcmp(c, "mv") == 0) { + cmd = CMD_MOV; + nb_arg = 2; + } else if (strcmp(c, "remove") == 0 || strcmp(c, "rm") == 0) { + cmd = CMD_DEL; + nb_arg = 1; + } else + goto out_enocmd; + + if ((argc - 1) <= nb_arg) + goto out_enoarg; + + for (i = 0; i < nb_arg; i++) + rule->argv[i] = argv[i + 1]; + + rule->cmd = cmd; + return nb_arg; +out_enoarg: + fprintf(stderr, "error: not enough argument for: %s\n", c); + return 0; +out_enocmd: + fprintf(stderr, "error: unknown cmd: %s\n", c); + return 0; + +} + +static void export_part_as(struct part *part, char *name1, char *name2) +{ + char s[1024]; + int size; + + memset(s, 0, sizeof(char) * 1024); + size = snprintf(s, 1024, "--- %s\n+++ %s\n", name1, name2); + + write(STDOUT_FILENO, s, size); + write(STDOUT_FILENO, part->data, part->end - part->data); +} + + +static int match_rule(char *name, struct rule *rule) +{ + if (strstr(name, rule->argv[0])) + return 1; + return 0; +} + +static char * mk_copy_name(char *name, struct rule *rule) +{ + return NULL; +} + +static int do_part(struct part *part, struct rule *rules) +{ + int deleted = 0; + char *copy_name = NULL; + int r; + + for (r = 0; r < MAX_RULES; r++) { + if (rules[r].cmd == CMD_NO) + continue; + + if (!match_rule(part->filename[1], &rules[r])) + continue; + + switch (rules[r].cmd) { + case CMD_DEL: + deleted = 1; + break; + case CMD_MOV: + copy_name = mk_copy_name(part->filename[1], + &rules[r]); + deleted = 1; + break; + case CMD_CPY: + copy_name = mk_copy_name(part->filename[1], + &rules[r]); + break; + default: + break; + } + } + if (copy_name) + export_part_as(part, copy_name, copy_name); + if (!deleted) + export_part_as(part, part->filename[0], part->filename[1]); +} + +int cmd_modify(int argc, char **argv) +{ + struct patch *patch; + char *filename = NULL; + struct list_head *tmp; + struct rule rules[MAX_RULES]; + int i, r; + int no_more_option = 0; + + if (argc < 2) + usage("modify"); + + memset(rules, 0, sizeof(struct rule) * 64); + /* + * --cp /arch/i386/ /arch/xen/i386/ + * --cp /include/i386/ /include/xen/i386/ + * --mv /arch/i386/ /arch/xen/i386/ + * --rm /arch/i386/Kconfig + */ + for (i = r = 0; i < argc && (r < MAX_RULES); i++) { + if (!no_more_option && strncmp(argv[i], "--", 2) == 0) { + if (!argv[i][3]) { + int ret; + ret = parse_rule(argc - i, &argv[i], &rules[r]); + if (ret > 0) + r++; + i += ret; + } + else + no_more_option = 1; + } else + filename = argv[i]; + } + + if (!filename) + usage("modify"); + + patch = open_patch(filename); + + list_for_each(&patch->parts, tmp) { + struct part *part = list_entry(tmp, struct part, list); + + do_part(part, rules); + + } + + close_patch(patch); + + return 0; +} diff -Naur patchtool-0.5/cmd_version.c patchtool-0.6/cmd_version.c --- patchtool-0.5/cmd_version.c 1970-01-01 00:00:00.000000000 +0000 +++ patchtool-0.6/cmd_version.c 2005-04-13 22:25:27.000000000 +0000 @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2005 Vincent Hanquez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 only. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include + +int cmd_version(int argc, char **argv) +{ + printf("0.6.0\n"); + return 1; +} diff -Naur patchtool-0.5/Makefile patchtool-0.6/Makefile --- patchtool-0.5/Makefile 2005-04-12 00:08:25.000000000 +0000 +++ patchtool-0.6/Makefile 2005-04-16 21:27:57.000000000 +0000 @@ -1,14 +1,14 @@ CC = gcc CFLAGS = -O2 -g -Wall -OBJS += patchtool.o -OBJS += parse.o -OBJS += patch.o -OBJS += list.o +OBJS += patchtool.o parse.o patch.o list.o + +OBJS += cmd_version.o OBJS += cmd_split.o OBJS += cmd_list.o OBJS += cmd_get.o OBJS += cmd_sparse.o +OBJS += cmd_modify.o all: patchtool diff -Naur patchtool-0.5/parse.c patchtool-0.6/parse.c --- patchtool-0.5/parse.c 2005-04-12 21:03:27.000000000 +0000 +++ patchtool-0.6/parse.c 2005-04-16 21:25:20.000000000 +0000 @@ -45,35 +45,76 @@ return new; } +static void parse_hunk_error(char *s, int d) +{ + char *end = strchr(s, '\n'); + int i = end - s; + if (!end) { + fprintf(stderr, "error: parsing hunk(%d)\n", d); + return; + } + fprintf(stderr, "error: parsing hunk(%d): \"%.*s\"\n", + d, i, s); + return; +} + +#define HUNK_PROBLEM_OUT(ptr, d) { \ + parse_hunk_error(ptr, d); \ + goto out; \ + } + /* processing part */ static char *parse_hunk_header(struct patch *p, struct part *part, struct hunk *hunk, char *tmp) { - int ret; + unsigned long ret; + char *end, *start; - if (strncmp(tmp, "@@ ", 2) != 0) { - fprintf(stderr, "error: hunk problem\n"); - return parser_next_line(tmp); - } - - ret = sscanf(tmp, "@@ -%d,%d +%d,%d @@", &hunk->off[0], &hunk->line[0], - &hunk->off[1], &hunk->line[1]); - if (ret != 4) { - hunk->off[1] = 0; - ret = sscanf(tmp, "@@ -%d,%d +%d @@", &hunk->off[0], &hunk->line[0], - &hunk->line[1]); - if (ret != 3) { - ret = sscanf(tmp, "@@ -%d +%d,%d @@", &hunk->off[0], - &hunk->off[1], &hunk->line[1]); - if (ret != 3) { - fprintf(stderr, "error: not enough arg " - "in hunk: \"\"%.30s\"\"\n", tmp); - return parser_next_line(tmp); - } - hunk->off[0] = hunk->line[0] = -1; - } - } + hunk->off[0] = hunk->off[1] = hunk->line[0] = hunk->line[1] = -1; + + start = tmp; + if (strncmp(tmp, "@@ -", 4) != 0) + HUNK_PROBLEM_OUT(start, 0); + + tmp += 4; + /* first part -%d,%d or -%d */ + ret = strtoul(tmp, &end, 10); + if (ret == 0 && tmp == end && !*end) + HUNK_PROBLEM_OUT(start, 1); + + if (*end == ',') { + hunk->off[0] = ret; + tmp = end + 1; + ret = strtoul(tmp, &end, 10); + if (ret == 0 && tmp == end && !*end) + HUNK_PROBLEM_OUT(start, 2); + hunk->line[0] = ret; + } + + if (strncmp(end, " +", 2) != 0) + HUNK_PROBLEM_OUT(start, 3); + tmp = end + 2; + + /* second part +%d,%d or +%d */ + ret = strtoul(tmp, &end, 10); + if (ret == 0 && tmp == end && !*end) + HUNK_PROBLEM_OUT(start, 4); + + if (*end == ',') { + hunk->off[1] = ret; + tmp = end + 1; + ret = strtoul(tmp, &end, 10); + if (ret == 0 && tmp == end && !*end) + HUNK_PROBLEM_OUT(start, 5); + hunk->line[1] = ret; + } else + hunk->line[1] = ret; + + tmp = end; + if (strncmp(tmp, " @@", 3) != 0) + HUNK_PROBLEM_OUT(start, 6); +out: return parser_next_line(tmp); } @@ -184,6 +225,7 @@ part->filename[1] = part_get_filename(tmp + 4); tmp = parser_next_line(tmp); + part->data = tmp; while (tmp && *tmp && (strncmp(tmp, "@@ ", 3) == 0)) tmp = parse_hunk(p, part, tmp); diff -Naur patchtool-0.5/patch.h patchtool-0.6/patch.h --- patchtool-0.5/patch.h 2005-03-28 18:58:44.000000000 +0000 +++ patchtool-0.6/patch.h 2005-04-16 15:19:24.000000000 +0000 @@ -27,8 +27,8 @@ struct hunk { - int off[2]; - int line[2]; + signed int off[2]; + signed int line[2]; int tlines[3]; char *start; char *data; @@ -40,6 +40,7 @@ { char *filename[2]; char *start; + char *data; char *end; int nb_hunks; struct list_head hunks; diff -Naur patchtool-0.5/patchtool.c patchtool-0.6/patchtool.c --- patchtool-0.5/patchtool.c 2005-04-13 10:29:23.000000000 +0000 +++ patchtool-0.6/patchtool.c 2005-04-16 16:55:11.000000000 +0000 @@ -31,6 +31,8 @@ else match_cmd(list) else match_cmd(sparse) else match_cmd(get) + else match_cmd(modify) + else match_cmd(version) else usage(NULL); return 0;