|
|
1.1 root 1: static char *rcsid = "$Header$";
2: /*
3: * pdiff - differential project comparator
4: *
5: * Author: Peter J. Nicklin
6: */
7: #include <stdio.h>
8: #include "getarg.h"
9: #include "macro.h"
10: #include "null.h"
11: #include "path.h"
12: #include "pdb.h"
13: #include "pdtyp.h"
14: #include "pld.h"
15: #include "ptree.h"
16: #include "spms.h"
17: #include "yesno.h"
18:
19: char **NARGV; /* new argument list */
20: char *PGN = "pdiff"; /* program name */
21: int EXECUTE = YES; /* execute command? */
22: int NARGI = 0; /* new argument list index */
23: int RECURSIVE = 0; /* recursively compare projects */
24: PDTYP PDIRTYP; /* project directory type labels list */
25:
26: main(argc, argv)
27: int argc;
28: char **argv;
29: {
30: extern int PPDEBUG; /* project pathname debug flag */
31: char p1[PPATHSIZE]; /* project pathname buffer */
32: char p2[PPATHSIZE]; /* project pathname buffer */
33: char *strcpy(); /* string copy */
34: int balance(); /* balance PDIR structs */
35: int diffdir(); /* compare directories or files */
36: int diffproject(); /* compare projects */
37: int pdtparse(); /* parse boolean type label expr */
38: int read_path(); /* read project or regular pathname */
39: int status = 0; /* exit status */
40: PATH pb1; /* pathname struct buffer 1 */
41: PATH pb2; /* pathname struct buffer 2 */
42: unsigned long pathtyp1; /* type of pathname 1 */
43: unsigned long pathtyp2; /* type of pathname 2 */
44:
45: NARGV = argv;
46: NARGV[NARGI++] = "diff";
47:
48: {
49: register char *s; /* option pointer */
50: while (--argc > 0 && **++argv == '-')
51: {
52: for (s = argv[0]+1; *s != '\0'; s++)
53: switch (*s)
54: {
55: case 'D':
56: PPDEBUG = YES;
57: break;
58: case 'T':
59: if (pdtparse(GETARG(s), &PDIRTYP) == NO)
60: status = 1;
61: goto endfor;
62: case 'r':
63: RECURSIVE++;
64: break;
65: case 'x':
66: EXECUTE = NO;
67: break;
68: default:
69: NARGV[NARGI++] = *argv;
70: break;
71: }
72: endfor: continue;
73: }
74: }
75: if (status == 1 || argc < 2)
76: {
77: warn("usage: pdiff [-rx] [-T typexpr] [diff options] p1 p2");
78: exit(2);
79: }
80:
81: strcpy(p1, argv[0]);
82: strcpy(p2, argv[1]);
83: NARGV[NARGI+2] = NULL;
84:
85: if (read_path(p1, &pb1) == NO || read_path(p2, &pb2) == NO)
86: exit(2);
87:
88: pathtyp1 = (pb1.p_mode & P_IFMT);
89: pathtyp2 = (pb2.p_mode & P_IFMT);
90:
91: if (pathtyp1 == P_IFPROOT || pathtyp1 == P_IFHOME)
92: {
93: if (pathtyp2 == P_IFPROOT || pathtyp2 == P_IFHOME)
94: status = diffproject(p1, pb1.p_path, p2, pb2.p_path);
95: else if (balance(p1, &pb1, &pb2) == NO)
96: exit(2);
97: else
98: status = diffdir(p1, pb1.p_path, p2, pb2.p_path);
99: }
100: else if (pathtyp2 == P_IFPROOT || pathtyp2 == P_IFHOME)
101: {
102: if (balance(p2, &pb2, &pb1) == NO)
103: exit(2);
104: else
105: status = diffdir(p1, pb1.p_path, p2, pb2.p_path);
106: }
107: else {
108: status = diffdir(p1, pb1.p_path, p2, pb2.p_path);
109: }
110:
111: if (status > 1)
112: status = 2;
113: exit(status);
114: }
115:
116:
117:
118: /*
119: * balance() balances a PATH struct given a project and a directory or file.
120: * If a regular directory or file, then it is assumed to be relative to the
121: * current working project directory. Returns NO if balancing fails, otherwise
122: * YES. The project pathname p1 is updated to reflect the balancing.
123: */
124: balance(p1, pb1, pb2)
125: char *p1; /* we know this is a project root dir */
126: PATH *pb1; /* project root directory buffer */
127: PATH *pb2; /* (project) directory or file buffer */
128: {
129: char *pathcat(); /* regular pathname concatenation */
130: char *ppathcat(); /* project pathname concatenation */
131: int getcpd(); /* get current working project dir */
132: int read_path(); /* read project or regular pathname */
133: PATH cpathbuf; /* current pathname struct buffer */
134:
135: if ((pb2->p_mode&P_IFMT) == P_IFPDIR)
136: {
137: ppathcat(p1, p1, pb2->p_alias);
138: return(read_path(p1, pb1));
139: }
140: else if (*pb2->p_path == _RDIRC || getcpd(&cpathbuf) != 1)
141: {
142: warn("don't know which project directory to use in %s", p1);
143: return(NO);
144: }
145: else {
146: ppathcat(p1, p1, cpathbuf.p_alias);
147: pathcat(p1, p1, pb2->p_path);
148: return(read_path(p1, pb1));
149: }
150: }
151:
152:
153:
154: /*
155: * diffdir() compares two directories or files. Returns whatever diff()
156: * returns.
157: */
158: diffdir(pp1, d1, pp2, d2)
159: char *pp1; /* project pathname */
160: char *d1; /* directory or file pathname */
161: char *pp2; /* project pathname */
162: char *d2; /* directory or file pathname */
163: {
164: static int have_printed; /* has printing already been done? */
165: int diff(); /* fork diff program */
166: int iargi; /* argument index */
167:
168: if (have_printed)
169: putchar('\n');
170: have_printed = 1;
171: printf("==> ");
172: for (iargi = 0; iargi < NARGI; iargi++)
173: printf("%s ", NARGV[iargi]);
174: printf("%s %s <==\n", pp1, pp2);
175: fflush(stdout);
176:
177: if (EXECUTE == NO)
178: return(0);
179:
180: NARGV[NARGI] = d1;
181: NARGV[NARGI+1] = d2;
182: return(diff(NARGV));
183: }
184:
185:
186:
187: /*
188: * diffproject() compares two projects, recursively if necessary. Returns
189: * 0 if no differences, 1 if some, 2 if trouble.
190: */
191: diffproject(pp1, p1, pp2, p2)
192: char *pp1; /* project pathname */
193: char *p1; /* project root directory pathname */
194: char *pp2; /* project pathname */
195: char *p2; /* project root directory pathname */
196: {
197: int closepdb(); /* close database */
198: int diffpdtree(); /* diff project directory tree */
199: int diffptree(); /* diff tree of projects */
200: int errpdb(); /* print database error message */
201: int pdtmatch(); /* match project dir type label expr */
202: int status = 0; /* return status */
203: PATH *pd; /* pathname struct pointer */
204: PATH *readpld(); /* read project link directory entry */
205: PDB *openpdb(); /* open database */
206: PDB *pldp; /* project link directory stream */
207: PTREE *proot; /* root of project tree */
208: PTREE *pdroot; /* root of project directory tree */
209: PTREE *ptree(); /* search and insert in proj dir tree */
210: void ptreerm(); /* remove project directory tree */
211:
212: proot = NULL;
213: pdroot = NULL;
214:
215: /* read PLDNAME project link directory belonging to p1 */
216: if ((pldp = openpdb(PLDNAME, p1, "r")) == NULL)
217: {
218: errpdb((PDB *) NULL);
219: return(2);
220: }
221: while ((pd = readpld(pldp)) != NULL)
222: {
223: if (EQUAL(pd->p_alias, PARENTPROJECT))
224: continue;
225: else if (EQUAL(pd->p_alias, CURPROJECT))
226: {
227: if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES)
228: pdroot = ptree(pdroot, "", pd->p_path, CNULL);
229: }
230: else if (pd->p_mode == P_IFPROOT)
231: {
232: if (RECURSIVE)
233: proot = ptree(proot, pd->p_alias, pd->p_path, CNULL);
234: }
235: else if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES)
236: pdroot = ptree(pdroot, pd->p_alias, pd->p_path, CNULL);
237: }
238: closepdb(pldp);
239:
240: /* read PLDNAME project link directory belonging to p2 */
241: if ((pldp = openpdb(PLDNAME, p2, "r")) == NULL)
242: {
243: errpdb((PDB *) NULL);
244: return(2);
245: }
246: while ((pd = readpld(pldp)) != NULL)
247: {
248: if (EQUAL(pd->p_alias, PARENTPROJECT))
249: continue;
250: else if (EQUAL(pd->p_alias, CURPROJECT))
251: {
252: if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES)
253: pdroot = ptree(pdroot, "", CNULL, pd->p_path);
254: }
255: else if (pd->p_mode == P_IFPROOT)
256: {
257: if (RECURSIVE)
258: proot = ptree(proot, pd->p_alias, CNULL, pd->p_path);
259: }
260: else if (PDIRTYP.pfxsize==0 || pdtmatch(&PDIRTYP,pd->p_type)==YES)
261: pdroot = ptree(pdroot, pd->p_alias, CNULL, pd->p_path);
262: }
263: closepdb(pldp);
264:
265: /* diff project directory tree */
266: status |= diffpdtree(pdroot, pp1, pp2);
267: ptreerm(pdroot);
268:
269: /* diff subprojects */
270: status |= diffptree(proot, pp1, pp2);
271: ptreerm(proot);
272:
273: return(status);
274: }
275:
276:
277:
278: /*
279: * diffpdtree() compares project directories in a project directory tree.
280: */
281: diffpdtree(p, pp1, pp2)
282: PTREE *p; /* current node in project dir tree */
283: char *pp1; /* project pathname */
284: char *pp2; /* project pathname */
285: {
286: char ppathbuf1[PPATHSIZE]; /* project pathname buffer */
287: char ppathbuf2[PPATHSIZE]; /* project pathname buffer */
288: char *ppathcat(); /* project pathname concantenation */
289: int diffdir(); /* compare directories or files */
290: int status = 0; /* return status */
291: void printonly(); /* print "only in project ..." mesg */
292:
293: if (p == NULL)
294: return(0);
295: status |= diffpdtree(p->left, pp1, pp2);
296: if (p->pd1 == NULL)
297: printonly(pp2, p->alias);
298: else if (p->pd2 == NULL)
299: printonly(pp1, p->alias);
300: else {
301: ppathcat(ppathbuf1, pp1, p->alias);
302: ppathcat(ppathbuf2, pp2, p->alias);
303: status |= diffdir(ppathbuf1, p->pd1, ppathbuf2, p->pd2);
304: }
305: status |= diffpdtree(p->right, pp1, pp2);
306: return(status);
307: }
308:
309:
310:
311: /*
312: * diffptree() compares projects in a project tree.
313: */
314: diffptree(p, pp1, pp2)
315: PTREE *p; /* current node in project tree */
316: char *pp1; /* project pathname */
317: char *pp2; /* project pathname */
318: {
319: char ppathbuf1[PPATHSIZE]; /* project pathname buffer */
320: char ppathbuf2[PPATHSIZE]; /* project pathname buffer */
321: char *ppathcat(); /* project pathname concantenation */
322: int diffproject(); /* compare projects */
323: int status = 0; /* return status */
324: void printonly(); /* print "only in project ..." mesg */
325:
326: if (p == NULL)
327: return(0);
328: status |= diffptree(p->left, pp1, pp2);
329: if (p->pd1 == NULL)
330: printonly(pp2, p->alias);
331: else if (p->pd2 == NULL)
332: printonly(pp1, p->alias);
333: else {
334: ppathcat(ppathbuf1, pp1, p->alias);
335: ppathcat(ppathbuf2, pp2, p->alias);
336: status |= diffproject(ppathbuf1, p->pd1, ppathbuf2, p->pd2);
337: }
338: status |= diffptree(p->right, pp1, pp2);
339: return(status);
340: }
341:
342:
343:
344: /*
345: * printonly() prints "only in project ..." message.
346: */
347: void
348: printonly(project, pdirname)
349: char *project; /* project pathname */
350: char *pdirname; /* unique project directory */
351: {
352: printf("Only in project %s: %s\n", project,
353: (*pdirname == '\0') ? CURPROJECT : pdirname);
354: fflush(stdout);
355: }
356:
357:
358:
359: /*
360: * read_path() loads a PATH struct given a regular or project pathname.
361: * Returns integer NO if an invalid pathname or non-existent target,
362: * otherwise YES.
363: */
364: read_path(pathname, pb)
365: char *pathname; /* regular or project pathname */
366: PATH *pb; /* pathname struct buffer */
367: {
368: int readpath(); /* read project or regular pathname */
369:
370: if (readpath(pathname, pb) == -1 || (pb->p_mode & P_IFMT) == P_IFNEW)
371: {
372: patherr(pathname);
373: return(NO);
374: }
375: return(YES);
376: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.