1#!/usr/bin/php
2
3<?php
4/*
5RCS file: /cvsroot/tools/org.eclipse.emf/.cvsignore,v //store
6Working file: .cvsignore //don't need to store, basename(rcs file), minus ,v?
7head: 1.1 //maybe store, could be calculated based on tags table?
8branch: //probably store, what does this actually mean?, never used (always empty)?
9locks: strict //store, though not used (always strict)?
10access list: //store, though not used (always empty)?
11symbolic names: //do we actually need to store these? we'll see
12        build_200608030000: 1.1
13	...
14keyword substitution: kv //store, 'b', 'k', 'kv', 'kvl', 'v' are (currently) used
15total revisions: 2;     selected revisions: 2 //don't store, is count of commits to the file
16description: //is this a title for the revisions? probably
17----------------------------
18revision 1.1
19date: 2004/03/06 18:22:28;  author: marcelop;  state: Exp;
20branches:  1.1.2;
21Move the EMF, XSD and SDO source code to the Eclipse.org repository
22----------------------------
23revision 1.1.2.1
24date: 2005/06/02 16:09:17;  author: nickb;  state: Exp;  lines: +0 -0
25*** empty log message ***
26=============================================================================
27*/
28
29$db = "modeling"; /* database name. change this to match your project or can leave as is */
30
31$perfile_regex = "/^RCS\ file:\ (.+?$)\\n
32	^Working\ file:\ (.+?$)\\n
33	^head:\ (.+?$)\\n
34	^branch:\ ?(.*?$)\\n
35	^locks:\ (.+?$)\\n
36	^access\ list:\ ?(.*?$)\\n
37	(?:^symbolic\ names:\ ?(.*?$)\\n
38	((?:^\\t\S+:\ [0-9\.]+$\\n)+))?
39	^keyword\ substitution:\ (.+?$)\\n
40	^total\ revisions:\ (\d+);\\tselected\ revisions:\ (\d+)$\\n
41	^description:\ ?(.*?$)\\n
42	^((?:\-{28}.+$\\n)?
43	^={77})$/smx";
44
45$percommit_regex = "#^\-{28}$\\n
46	^revision\ ([0-9\.]+)$\\n
47	^date:\ (\d{4}/\d\d/\d\d\ \d\d:\d\d:\d\d);\ \ author:\ (\S+);\ \ state:\ (\S+);(?:\ \ lines:\ \+(\d+)\ \-(\d+))?$\\n
48	(?:^branches:(?:\ \ ([0-9\.]+);)+$\\n)?
49	^(.+?)$\\n
50	^(?:\-{28}|={77})#smx";
51
52$bugs_regex = "@(?:
53        \[\#?(\d+)\]
54        |
55        (?:Bugzilla)?\#(\d+)
56        |
57        https?\Q://bugs.eclipse.org/bugs/show_bug.cgi?id=\E(\d+)
58        )@x";
59
60include_once "includes/parsecvs-dbaccess.php";
61$connect = mysql_connect($dbhost, $dbuser, $dbpass) or die("Couldn't connect to database!\n");
62mysql_select_db($db, $connect) or die(mysql_error());
63$file = file_get_contents(($argv[1] ? $argv[1] : "php://stdin"));
64
65wmysql_query("CREATE TEMPORARY TABLE `tmptags` (`tagname` VARBINARY(255), `revision` VARCHAR(20), PRIMARY KEY (`tagname`)) ENGINE = memory");
66
67preg_match_all("/^(RCS file:.+?^={77}$)/sm", $file, $regs) or die("Couldn't find any cvs logs!\n");
68foreach ($regs[0] as $z)
69{
70	/* parse each file's info */
71	if (preg_match($perfile_regex, $z, $props))
72	{
73		$esc = array(1, 3, 9);
74		foreach ($esc as $y)
75		{
76			$props[$y] = mysql_real_escape_string($props[$y], $connect);
77		}
78		preg_match("/^\/cvsroot\/[^\/]+\/([^\/]+)\//", $props[1], $proj);
79		$q = "`project` = '$proj[1]', `head` = '$props[3]', `keyword_subs` = '$props[9]'";
80		wmysql_query("INSERT INTO `cvsfiles` SET `cvsname` = '$props[1]', $q ON DUPLICATE KEY UPDATE $q");
81		/* mysql_insert_id() won't work if we updated rather than inserted */
82		$result = wmysql_query("SELECT `fid` FROM `cvsfiles` WHERE `cvsname` = '$props[1]'");
83		$row = mysql_fetch_row($result);
84
85		/* parse symbolic names */
86		$tags = array();
87		$filetags = array();
88		$count = preg_match_all("/^\t(\S+): ([0-9\.]+)$\n/m", $props[8], $syms);
89		for ($i=0;$i<$count;$i++)
90		{
91			array_push($filetags, "('{$syms[1][$i]}', '{$syms[2][$i]}')");
92		}
93		if ($count > 0)
94		{
95			$syms[1] = preg_replace("/^(.+)$/e", "fixup('$1')", $syms[1]);
96			wmysql_query("INSERT INTO `tags` (`tagname`, `tagdate`) VALUES " . join($syms[1], ",") . " ON DUPLICATE KEY UPDATE `tid` = `tid`");
97			wmysql_query("INSERT INTO `tmptags` (`tagname`, `revision`) VALUES " . join($filetags, ","));
98			wmysql_query("INSERT INTO `filetags` SELECT $row[0], `tid`, `revision` FROM `tmptags` NATURAL JOIN `tags` ON DUPLICATE KEY UPDATE `filetags`.`revision` = `tmptags`.`revision`");
99			wmysql_query("TRUNCATE TABLE `tmptags`");
100		}
101
102		$commits = $props[13];
103		/* parse commits */
104		while (preg_match($percommit_regex, $commits, $revs))
105		{
106			$commits = substr($commits, strlen($revs[0]) - 28); //leave the \-{28} in tact
107			$revs[8] = mysql_real_escape_string($revs[8], $connect);
108			$q = "`date` = STR_TO_DATE('$revs[2]', '%Y/%m/%d %T'), `author` = '$revs[3]', `state` = '$revs[4]', `linesplus` = '$revs[5]', `linesminus` = '$revs[6]', `message` = '$revs[8]'";
109			wmysql_query("INSERT INTO `commits` SET `fid` = '$row[0]', `revision` = '$revs[1]', $q ON DUPLICATE KEY UPDATE $q");
110
111			/* parse bug numbers */
112			if (preg_match_all($bugs_regex, $revs[8], $ubugs))
113			{
114				unset($ubugs[0]);
115				$bugs = extract_bugs($ubugs);
116				$bugs = preg_replace("/^(.+)$/", "('$row[0]', '$revs[1]', '$1')", $bugs);
117				wmysql_query("INSERT INTO `bugs` (`fid`, `revision`, `bugid`) VALUES " . join($bugs, ",") . " ON DUPLICATE KEY UPDATE `bugid` = `bugid`");
118			}
119		}
120	}
121}
122wmysql_query("DROP TEMPORARY TABLE `tmptags`");
123
124$tables = array();
125mysql_select_db("INFORMATION_SCHEMA") or die(mysql_error());
126$result = wmysql_query("SELECT TABLE_NAME FROM TABLES WHERE `TABLE_SCHEMA` = '$db' AND `TABLE_TYPE` = 'BASE TABLE'");
127while ($row = mysql_fetch_row($result))
128{
129	array_push($tables, $row[0]);
130}
131
132mysql_select_db($db) or die(mysql_error());
133wmysql_query("OPTIMIZE TABLE " . join($tables, ","));
134wmysql_query("ANALYZE TABLE " . join($tables, ","));
135mysql_close($connect);
136
137function fixup($str)
138{
139	return "('$str', " . (preg_match("/^build_(\d{12})$/", $str, $regs) ? "STR_TO_DATE('$regs[1]', '%Y%m%d%k%i')" : "NULL") . ")";
140}
141
142function wmysql_query($sql)
143{
144	$res = mysql_query($sql) or die("$sql\n" . mysql_error() . "\n");
145	return $res;
146}
147
148function extract_bugs($regs)
149{
150        foreach ($regs as $z)
151        {
152                foreach ($z as $y)
153                {
154                        if (preg_match("/^\d+$/", $y))
155                        {
156                                $bugs[] = $y;
157                        }
158                }
159        }
160
161        return $bugs;
162}
163?>
164