degrade-cvs_direct-failure.p
[cvsps/4msysgit.git] / cap.c
blob6bb316cc52dc93ac1ff5de2ea80cf2361c5ce4e9
1 /*
2 * Copyright 2001, 2002, 2003 David Mansfield and Cobite, Inc.
3 * See COPYING file for license information
4 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
10 #include <cbtcommon/debug.h>
11 #include <cbtcommon/text_util.h>
13 #include "cap.h"
14 #include "cvs_direct.h"
16 extern CvsServerCtx * cvs_direct_ctx;
18 static char client_version[BUFSIZ];
19 static char server_version[BUFSIZ];
21 static int check_cvs_version(int, int, int);
22 static int check_version_string(const char *, int, int, int);
24 int cvs_check_cap(int cap)
26 int ret;
28 switch(cap)
30 case CAP_HAVE_RLOG:
31 if (!(ret = check_cvs_version(1,11,1)))
33 debug(DEBUG_APPERROR,
34 "WARNING: Your CVS client version:\n[%s]\n"
35 "and/or server version:\n[%s]\n"
36 "are too old to properly support the rlog command. \n"
37 "This command was introduced in 1.11.1. Cvsps\n"
38 "will use log instead, but PatchSet numbering\n"
39 "may become unstable due to pruned empty\n"
40 "directories.\n", client_version, server_version);
42 break;
44 default:
45 debug(DEBUG_APPERROR, "unknown cvs capability check %d", cap);
46 exit(1);
49 return ret;
52 static void get_version_external()
54 FILE * cvsfp;
56 strcpy(client_version, "(UNKNOWN CLIENT)");
57 strcpy(server_version, "(UNKNOWN SERVER)");
59 #ifdef __MINGW32__
60 if (!(cvsfp = popen("cvs version 2>nul", "r")))
61 #else
62 if (!(cvsfp = popen("cvs version 2>/dev/null", "r")))
63 #endif
65 debug(DEBUG_APPERROR, "cannot popen cvs version. exiting");
66 exit(1);
69 if (!fgets(client_version, BUFSIZ, cvsfp))
71 debug(DEBUG_APPMSG1, "WARNING: malformed CVS version: no data");
72 goto out;
75 chop(client_version);
77 if (strncmp(client_version, "Client", 6) == 0)
79 if (!fgets(server_version, BUFSIZ, cvsfp))
81 debug(DEBUG_APPMSG1, "WARNING: malformed CVS version: no server data");
82 goto out;
84 chop(server_version);
86 else
88 server_version[0] = 0;
91 out:
92 pclose(cvsfp);
95 int check_cvs_version(int req_major, int req_minor, int req_extra)
97 if (!client_version[0])
99 if (cvs_direct_ctx)
100 cvs_version(cvs_direct_ctx, client_version, server_version);
101 else
102 get_version_external();
105 return (check_version_string(client_version, req_major, req_minor, req_extra) &&
106 (!server_version[0] || check_version_string(server_version, req_major, req_minor, req_extra)));
109 int check_version_string(const char * str, int req_major, int req_minor, int req_extra)
111 char * p;
112 int major, minor, extra;
113 int skip = 6;
115 p = strstr(str, "(CVS) ");
117 if (!p) {
118 p = strstr(str, "(CVSNT)");
119 skip = 8;
122 if (!p)
124 debug(DEBUG_APPMSG1, "WARNING: malformed CVS version str: %s", str);
125 return 0;
128 p += skip;
129 if (sscanf(p, "%d.%d.%d", &major, &minor, &extra) != 3)
131 debug(DEBUG_APPMSG1, "WARNING: malformed CVS version: %s", str);
132 return 0;
135 return (major > req_major ||
136 (major == req_major && minor > req_minor) ||
137 (major == req_major && minor == req_minor && extra >= req_extra));