4 * Copyright (C) Linus Torvalds 2005
13 static int verbose
= 0;
16 * This is a really stupid program that takes cvsps output, and
17 * generates a a long _shell_script_ that will create the GIT archive
20 * You've been warned. I told you it was stupid.
22 * NOTE NOTE NOTE! In order to do branches correctly, this needs
23 * the fixed cvsps that has the "Ancestor branch" tag output.
24 * Hopefully David Mansfield will update his distribution soon
25 * enough (he's the one who wrote the patch, so at least we don't
26 * have to figt maintainer issues ;)
31 * cvs2git --cvsroot=[root] --module=[module] > script
33 * Creates a shell script that will generate the .git archive of
34 * the names CVS repository.
36 * IMPORTANT NOTE ABOUT "cvsps"! This requires version 2.1 or better,
37 * and the "TZ=UTC" and the "-A" flag is required for sane results!
45 static const char *cvsroot
;
46 static const char *cvsmodule
;
48 static char date
[100];
49 static char author
[100];
50 static char branch
[100];
51 static char ancestor
[100];
53 static char log
[32768];
54 static int loglen
= 0;
55 static int initial_commit
= 1;
57 static void lookup_author(char *n
, char **name
, char **email
)
60 * FIXME!!! I'm lazy and stupid.
62 * This could be something like
64 * printf("lookup_author '%s'\n", n);
65 * *name = "$author_name";
66 * *email = "$author_email";
68 * and that would allow the script to do its own
69 * lookups at run-time.
75 static void prepare_commit(void)
77 char *author_name
, *author_email
;
80 lookup_author(author
, &author_name
, &author_email
);
82 printf("export GIT_COMMITTER_NAME=%s\n", author_name
);
83 printf("export GIT_COMMITTER_EMAIL=%s\n", author_email
);
84 printf("export GIT_COMMITTER_DATE='+0000 %s'\n", date
);
86 printf("export GIT_AUTHOR_NAME=%s\n", author_name
);
87 printf("export GIT_AUTHOR_EMAIL=%s\n", author_email
);
88 printf("export GIT_AUTHOR_DATE='+0000 %s'\n", date
);
93 src_branch
= *ancestor
? ancestor
: branch
;
94 if (!strcmp(src_branch
, "HEAD"))
95 src_branch
= "master";
96 printf("ln -sf refs/heads/'%s' .git/HEAD\n", src_branch
);
99 * Even if cvsps claims an ancestor, we'll let the new
100 * branch name take precedence if it already exists
104 if (!strcmp(src_branch
, "HEAD"))
105 src_branch
= "master";
106 printf("[ -e .git/refs/heads/'%s' ] && ln -sf refs/heads/'%s' .git/HEAD\n",
107 src_branch
, src_branch
);
110 printf("git-read-tree -m HEAD || exit 1\n");
111 printf("git-checkout-cache -f -u -a\n");
114 static void commit(void)
116 const char *cmit_parent
= initial_commit
? "" : "-p HEAD";
117 const char *dst_branch
;
120 printf("tree=$(git-write-tree)\n");
121 printf("cat > .cmitmsg <<EOFMSG\n");
123 /* Escape $ characters, and remove control characters */
124 for (i
= 0; i
< loglen
; i
++) {
125 unsigned char c
= log
[i
];
134 if (c
== '\n' || c
== '\t')
141 printf("\nEOFMSG\n");
142 printf("commit=$(cat .cmitmsg | git-commit-tree $tree %s)\n", cmit_parent
);
145 if (!strcmp(dst_branch
, "HEAD"))
146 dst_branch
= "master";
148 printf("echo $commit > .git/refs/heads/'%s'\n", dst_branch
);
150 printf("echo 'Committed (to %s):' ; cat .cmitmsg; echo\n", dst_branch
);
162 static void update_file(char *line
)
164 char *name
, *version
;
167 while (isspace(*line
))
170 line
= strchr(line
, ':');
174 line
= strchr(line
, '>');
179 line
= strchr(line
, '(');
180 if (line
) { /* "(DEAD)" */
181 printf("git-update-cache --force-remove '%s'\n", name
);
185 dir
= strrchr(name
, '/');
187 printf("mkdir -p %.*s\n", (int)(dir
- name
), name
);
189 printf("cvs -q -d %s checkout -r%s -p '%s/%s' > '%s'\n", cvsroot
, version
, cvsmodule
, name
, name
);
190 printf("git-update-cache --add -- '%s'\n", name
);
198 { "Author:", author
},
199 { "Branch:", branch
},
200 { "Ancestor branch:", ancestor
},
206 int main(int argc
, char **argv
)
208 static char line
[1000];
209 enum state state
= Header
;
212 for (i
= 1; i
< argc
; i
++) {
213 const char *arg
= argv
[i
];
214 if (!memcmp(arg
, "--cvsroot=", 10)) {
218 if (!memcmp(arg
, "--module=", 9)) {
222 if (!strcmp(arg
, "-v")) {
230 cvsroot
= getenv("CVSROOT");
232 if (!cvsmodule
|| !cvsroot
) {
233 fprintf(stderr
, "I need a CVSROOT and module name\n");
237 printf("[ -d .git ] && exit 1\n");
238 printf("git-init-db\n");
239 printf("mkdir -p .git/refs/heads\n");
240 printf("mkdir -p .git/refs/tags\n");
241 printf("ln -sf refs/heads/master .git/HEAD\n");
243 while (fgets(line
, sizeof(line
), stdin
) != NULL
) {
244 int linelen
= strlen(line
);
246 while (linelen
&& isspace(line
[linelen
-1]))
250 struct hdrentry
*entry
;
254 printf("# H: %s\n", line
);
255 for (entry
= hdrs
; entry
->name
; entry
++) {
256 int len
= strlen(entry
->name
);
259 if (memcmp(entry
->name
, line
, len
))
267 while (isspace(*val
)) {
271 memcpy(entry
->dest
, val
, linelen
+1);
278 printf("# L: %s\n", line
);
279 if (!strcmp(line
, "Members:")) {
280 while (loglen
&& isspace(log
[loglen
-1]))
287 if (loglen
+ linelen
+ 5 > sizeof(log
))
289 memcpy(log
+ loglen
, line
, linelen
);
291 log
[loglen
++] = '\n';
296 printf("# M: %s\n", line
);