2
Copyright (C) 2012 Andrew Caudwell (acaudwell@gmail.com)
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.
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.
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/>.
19
#include "gource_settings.h"
21
#include "formats/git.h"
22
#include "formats/gitraw.h"
23
#include "formats/custom.h"
24
#include "formats/hg.h"
25
#include "formats/bzr.h"
26
#include "formats/svn.h"
27
#include "formats/apache.h"
31
static int logmill_thread(void *lmill) {
33
RLogMill *logmill = static_cast<RLogMill*> (lmill);
41
RLogMill::RLogMill(const std::string& logfile)
44
logmill_thread_state = LOGMILL_STATE_STARTUP;
47
#if SDL_VERSION_ATLEAST(1,3,0)
48
thread = SDL_CreateThread( logmill_thread, "logmill", this );
50
thread = SDL_CreateThread( logmill_thread, this );
54
RLogMill::~RLogMill() {
58
if(thread) SDL_KillThread(thread);
62
void RLogMill::run() {
63
logmill_thread_state = LOGMILL_STATE_FETCHING;
65
#if defined(HAVE_PTHREAD) && !defined(_WIN32)
69
// unblock SIGINT so user can cancel
70
// NOTE: assumes SDL is using pthreads
72
sigaddset(&mask, SIGINT);
73
pthread_sigmask(SIG_UNBLOCK, &mask, 0);
76
std::string log_format = gGourceSettings.log_format;
80
clog = fetchLog(log_format);
82
} catch(SeekLogException& exception) {
83
error = "unable to read log file";
84
} catch(SDLAppException& exception) {
85
error = exception.what();
88
if(!clog && error.empty()) {
89
if(SDLAppDirExists(logfile)) {
90
if(!log_format.empty()) {
91
error = "failed to generate log file";
93
error = "directory not supported";
96
error = "unsupported log format (you may need to regenerate your log file)";
100
logmill_thread_state = clog ? LOGMILL_STATE_SUCCESS : LOGMILL_STATE_FAILURE;
103
void RLogMill::abort() {
104
// TODO: make abort nicer by notifying the log process
105
// we want to shutdown
107
while(logmill_thread_state <= LOGMILL_STATE_FETCHING) {
112
bool RLogMill::isFinished() {
113
return logmill_thread_state > LOGMILL_STATE_FETCHING;
116
int RLogMill::getStatus() {
117
return logmill_thread_state;
120
std::string RLogMill::getError() {
125
RCommitLog* RLogMill::getLog() {
127
while(logmill_thread_state <= LOGMILL_STATE_FETCHING) {
134
bool RLogMill::findRepository(boost::filesystem::path& dir, std::string& log_format) {
138
//fprintf(stderr, "find repository from initial path: %s\n", dir.string().c_str());
140
while(is_directory(dir)) {
142
if(is_directory(dir / ".git")) log_format = "git";
143
else if(is_directory(dir / ".hg")) log_format = "hg";
144
else if(is_directory(dir / ".bzr")) log_format = "bzr";
145
else if(is_directory(dir / ".svn")) log_format = "svn";
147
if(!log_format.empty()) {
148
//fprintf(stderr, "found '%s' repository at: %s\n", log_format.c_str(), dir.string().c_str());
152
if(!dir.has_parent_path()) return false;
154
dir = dir.parent_path();
161
RCommitLog* RLogMill::fetchLog(std::string& log_format) {
163
RCommitLog* clog = 0;
165
//if the log format is not specified and 'logfile' is a directory, recursively look for a version control repository.
166
//this method allows for something strange like someone who having an svn repository inside a git repository
167
//(in which case it would pick the svn directory as it would encounter that first)
169
if(log_format.empty() && logfile != "-") {
172
boost::filesystem::path repo_path(logfile);
174
if(is_directory(repo_path)) {
175
if(findRepository(repo_path, log_format)) {
176
logfile = repo_path.string();
179
} catch(boost::filesystem3::filesystem_error& error) {
183
//we've been told what format to use
184
if(log_format.size() > 0) {
185
debugLog("log-format = %s", log_format.c_str());
187
if(log_format == "git") {
188
clog = new GitCommitLog(logfile);
189
if(clog->checkFormat()) return clog;
192
clog = new GitRawCommitLog(logfile);
193
if(clog->checkFormat()) return clog;
197
if(log_format == "hg") {
198
clog = new MercurialLog(logfile);
199
if(clog->checkFormat()) return clog;
203
if(log_format == "bzr") {
204
clog = new BazaarLog(logfile);
205
if(clog->checkFormat()) return clog;
209
if(log_format == "cvs") {
210
clog = new CVSEXPCommitLog(logfile);
211
if(clog->checkFormat()) return clog;
215
if(log_format == "custom") {
216
clog = new CustomLog(logfile);
217
if(clog->checkFormat()) return clog;
221
if(log_format == "apache") {
222
clog = new ApacheCombinedLog(logfile);
223
if(clog->checkFormat()) return clog;
227
if(log_format == "svn") {
228
clog = new SVNCommitLog(logfile);
229
if(clog->checkFormat()) return clog;
233
if(log_format == "cvs2cl") {
234
clog = new CVS2CLCommitLog(logfile);
235
if(clog->checkFormat()) return clog;
242
// try different formats until one works
245
debugLog("trying git...");
246
clog = new GitCommitLog(logfile);
247
if(clog->checkFormat()) return clog;
252
debugLog("trying mercurial...");
253
clog = new MercurialLog(logfile);
254
if(clog->checkFormat()) return clog;
259
debugLog("trying bzr...");
260
clog = new BazaarLog(logfile);
261
if(clog->checkFormat()) return clog;
266
debugLog("trying git raw...");
267
clog = new GitRawCommitLog(logfile);
268
if(clog->checkFormat()) return clog;
273
debugLog("trying cvs-exp...");
274
clog = new CVSEXPCommitLog(logfile);
275
if(clog->checkFormat()) return clog;
280
debugLog("trying svn...");
281
clog = new SVNCommitLog(logfile);
282
if(clog->checkFormat()) return clog;
287
debugLog("trying cvs2cl...");
288
clog = new CVS2CLCommitLog(logfile);
289
if(clog->checkFormat()) return clog;
294
debugLog("trying custom...");
295
clog = new CustomLog(logfile);
296
if(clog->checkFormat()) return clog;
301
debugLog("trying apache combined...");
302
clog = new ApacheCombinedLog(logfile);
303
if(clog->checkFormat()) return clog;