Add CVS 1.12.11.
[dragonfly.git] / contrib / cvs-1.12.11 / src / create_adm.c
1 /*
2  * Copyright (c) 1992, Brian Berliner and Jeff Polk
3  * Copyright (c) 1989-1992, Brian Berliner
4  * 
5  * You may distribute under the terms of the GNU General Public License as
6  * specified in the README file that comes with the CVS source distribution.
7  * 
8  * Create Administration.
9  * 
10  * Creates a CVS administration directory based on the argument repository; the
11  * "Entries" file is prefilled from the "initrecord" argument.
12  */
13
14 #include "cvs.h"
15
16
17
18 /* update_dir includes dir as its last component.
19
20    Return value is 0 for success, or 1 if we printed a warning message.
21    Note that many errors are still fatal; particularly for unlikely errors
22    a fatal error is probably better than a warning which might be missed
23    or after which CVS might do something non-useful.  If WARN is zero, then
24    don't print warnings; all errors are fatal then.  */
25
26 int
27 Create_Admin (const char *dir, const char *update_dir, const char *repository,
28               const char *tag, const char *date, int nonbranch, int warn,
29               int dotemplate)
30 {
31     FILE *fout;
32     char *cp;
33     char *reposcopy;
34     char *tmp;
35
36     TRACE ( 1, "Create_Admin (%s, %s, %s, %s, %s, %d, %d, %d)",
37             dir, update_dir, repository, tag ? tag : "",
38             date ? date : "", nonbranch, warn, dotemplate );
39
40     if (noexec)
41         return 0;
42
43     tmp = xmalloc (strlen (dir) + 100);
44     (void) sprintf (tmp, "%s/%s", dir, CVSADM);
45     if (isfile (tmp))
46         error (1, 0, "there is a version in %s already", update_dir);
47
48     if (CVS_MKDIR (tmp, 0777) < 0)
49     {
50         /* We want to print out the entire update_dir, since a lot of
51            our code calls this function with dir == "." or dir ==
52            NULL.  I hope that gives enough information in cases like
53            absolute pathnames; printing out xgetcwd() or something would
54            be way too verbose in the common cases.  */
55
56         if (warn)
57         {
58             /* The reason that this is a warning, rather than silently
59                just skipping creating the directory, is that we don't want
60                CVS's behavior to vary subtly based on factors (like directory
61                permissions) which are not made clear to the user.  With
62                the warning at least we let them know what is going on.  */
63             error (0, errno, "warning: cannot make directory %s in %s",
64                    CVSADM, update_dir);
65             free (tmp);
66             return 1;
67         }
68         else
69             error (1, errno, "cannot make directory %s in %s",
70                    CVSADM, update_dir);
71     }
72
73     /* record the current cvs root for later use */
74
75     Create_Root (dir, original_parsed_root->original);
76     if (dir != NULL)
77         (void) sprintf (tmp, "%s/%s", dir, CVSADM_REP);
78     else
79         (void) strcpy (tmp, CVSADM_REP);
80     fout = CVS_FOPEN (tmp, "w+");
81     if (fout == NULL)
82     {
83         if (update_dir[0] == '\0')
84             error (1, errno, "cannot open %s", tmp);
85         else
86             error (1, errno, "cannot open %s/%s", update_dir, CVSADM_REP);
87     }
88     reposcopy = xstrdup (repository);
89     Sanitize_Repository_Name (reposcopy);
90
91     /* The top level of the repository is a special case -- we need to
92        write it with an extra dot at the end.  This trailing `.' stuff
93        rubs me the wrong way -- on the other hand, I don't want to
94        spend the time making sure all of the code can handle it if we
95        don't do it. */
96
97     if (strcmp (reposcopy, current_parsed_root->directory) == 0)
98     {
99         reposcopy = xrealloc (reposcopy, strlen (reposcopy) + 3);
100         strcat (reposcopy, "/.");
101     }
102
103     cp = reposcopy;
104
105     /*
106      * If the Repository file is to hold a relative path, try to strip off
107      * the leading CVSroot argument.
108      */
109     {
110     char *path = xmalloc (strlen (current_parsed_root->directory) + 2);
111
112     (void) sprintf (path, "%s/", current_parsed_root->directory);
113     if (strncmp (cp, path, strlen (path)) == 0)
114         cp += strlen (path);
115     free (path);
116     }
117
118     if (fprintf (fout, "%s\n", cp) < 0)
119     {
120         if (update_dir[0] == '\0')
121             error (1, errno, "write to %s failed", tmp);
122         else
123             error (1, errno, "write to %s/%s failed", update_dir, CVSADM_REP);
124     }
125     if (fclose (fout) == EOF)
126     {
127         if (update_dir[0] == '\0')
128             error (1, errno, "cannot close %s", tmp);
129         else
130             error (1, errno, "cannot close %s/%s", update_dir, CVSADM_REP);
131     }
132
133     /* now, do the Entries file */
134     if (dir != NULL)
135         (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT);
136     else
137         (void) strcpy (tmp, CVSADM_ENT);
138     fout = CVS_FOPEN (tmp, "w+");
139     if (fout == NULL)
140     {
141         if (update_dir[0] == '\0')
142             error (1, errno, "cannot open %s", tmp);
143         else
144             error (1, errno, "cannot open %s/%s", update_dir, CVSADM_ENT);
145     }
146     if (fclose (fout) == EOF)
147     {
148         if (update_dir[0] == '\0')
149             error (1, errno, "cannot close %s", tmp);
150         else
151             error (1, errno, "cannot close %s/%s", update_dir, CVSADM_ENT);
152     }
153
154     /* Create a new CVS/Tag file */
155     WriteTag (dir, tag, date, nonbranch, update_dir, repository);
156
157     TRACE (1, "Create_Admin");
158
159     free (reposcopy);
160     free (tmp);
161     return 0;
162 }