1 /*
2 Copyright (C) 2010 John Arbash Meinel <john@arbash-meinel.com>
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version
7 3 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "bzr.h"
19 #include "../gource_settings.h"
20
21 #include <boost/format.hpp>
22
23 Regex bzr_commit_regex("^ *([\\d.]+) (.+)\t(\\d{4})-(\\d+)-(\\d+)(?: \\{[^}]+})?(?: \\[merge\\])?$");
24 Regex bzr_file_regex("^ *([AMDR]) (.*[^/])$");
25
26 // parse Bazaar log entries (using the gource.style template)
27
logCommand()28 std::string BazaarLog::logCommand() {
29
30 std::string start = (!gGourceSettings.start_date.empty()) ? "date:"+gGourceSettings.start_date : "1";
31 std::string stop = (!gGourceSettings.stop_date.empty()) ? "date:"+gGourceSettings.stop_date : "-1";
32
33 std::string range = str(boost::format("%s..%s") % start % stop);
34
35 std::string log_command = str(boost::format("bzr log --verbose -r %s --short -n0 --forward") % range);
36
37 return log_command;
38 }
39
BazaarLog(const std::string & logfile)40 BazaarLog::BazaarLog(const std::string& logfile) : RCommitLog(logfile) {
41
42 log_command = logCommand();
43
44 //can generate log from directory
45 if(!logf && is_dir) {
46 logf = generateLog(logfile);
47
48 if(logf) {
49 success = true;
50 seekable = true;
51 }
52 }
53 }
54
generateLog(const std::string & dir)55 BaseLog* BazaarLog::generateLog(const std::string& dir) {
56
57 //does directory have a .bzr ?
58 std::string bzrdir = dir + std::string("/.bzr");
59 struct stat dirinfo;
60 int stat_rc = stat(bzrdir.c_str(), &dirinfo);
61 if(stat_rc!=0 || !(dirinfo.st_mode & S_IFDIR)) {
62 return 0;
63 }
64
65 std::string command = getLogCommand();
66
67 // do we have this client installed
68 requireExecutable("bzr");
69
70 createTempLog();
71
72 if(temp_file.size()==0) return 0;
73
74 char cmd_buff[2048];
75 snprintf(cmd_buff, 2048, "%s %s > %s", command.c_str(), dir.c_str(), temp_file.c_str());
76
77 int command_rc = systemCommand(cmd_buff);
78
79 if(command_rc != 0) {
80 return 0;
81 }
82
83 BaseLog* seeklog = new SeekLog(temp_file);
84
85 return seeklog;
86 }
87
parseCommit(RCommit & commit)88 bool BazaarLog::parseCommit(RCommit& commit) {
89
90 std::string line;
91 std::vector<std::string> entries;
92 int year, month, day;
93
94 if(!logf->getNextLine(line)) return false;
95
96 if (!bzr_commit_regex.match(line, &entries)) {
97 //debugLog("regex failed\n");
98 return false;
99 }
100
101 commit.username = entries[1];
102
103 year = atoi(entries[2].c_str());
104 month = atoi(entries[3].c_str());
105 day = atoi(entries[4].c_str());
106
107 struct tm time_str;
108
109 time_str.tm_year = year - 1900;
110 time_str.tm_mon = month - 1;
111 time_str.tm_mday = day;
112 time_str.tm_hour = 0;
113 time_str.tm_min = 0;
114 time_str.tm_sec = 0;
115 time_str.tm_isdst = -1;
116
117 commit.timestamp = mktime(&time_str);
118
119 while(logf->getNextLine(line) && line.size()) {
120 if (!bzr_file_regex.match(line, &entries)) continue;
121 commit.addFile(entries[1], entries[0]);
122 }
123
124 return true;
125 }
126