2
Copyright (C) 2009 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/>.
18
#include "commitlog.h"
20
std::string munge_utf8(const std::string& str) {
24
utf8::replace_invalid(str.begin(), str.end(), back_inserter(munged), '?');
35
RCommitLog::RCommitLog(const std::string& logfile, int firstChar) {
46
if(checkFirstChar(firstChar, std::cin)) {
47
logf = new StreamLog();
57
int rc = stat(logfile.c_str(), &fileinfo);
60
is_dir = (fileinfo.st_mode & S_IFDIR) ? true : false;
65
std::ifstream testf(logfile.c_str());
67
bool firstOK = checkFirstChar(firstChar, testf);
72
logf = new SeekLog(logfile);
80
RCommitLog::~RCommitLog() {
81
if(logf!=0) delete logf;
83
if(!temp_file.empty()) {
84
remove(temp_file.c_str());
88
//check firstChar of stream is as expected. if no firstChar defined just returns true.
89
bool RCommitLog::checkFirstChar(int firstChar, std::istream& stream) {
92
if(firstChar == -1) return true;
94
int c = stream.peek();
96
if(firstChar == c) return true;
101
bool RCommitLog::checkFormat() {
103
if(!success) return false;
105
//read a commit to see if the log is in the correct format
106
if(nextCommit(lastCommit)) {
109
//if the log is seekable, go back to the start
110
((SeekLog*)logf)->seekTo(0.0);
112
//otherwise set the buffered flag as we have bufferd one commit
122
std::string RCommitLog::getLogCommand() {
126
bool RCommitLog::isSeekable() {
130
bool RCommitLog::getCommitAt(float percent, RCommit& commit) {
131
if(!seekable) return false;
133
SeekLog* seeklog = ((SeekLog*)logf);
136
long currpointer = seeklog->getPointer();
137
std::string currlastline = lastline;
140
bool success = findNextCommit(commit,500);
143
seeklog->setPointer(currpointer);
144
lastline = currlastline;
149
bool RCommitLog::getNextLine(std::string& line) {
150
if(!lastline.empty()) {
152
lastline = std::string("");
156
return logf->getNextLine(line);
160
void RCommitLog::seekTo(float percent) {
161
if(!seekable) return;
165
((SeekLog*)logf)->seekTo(percent);
168
float RCommitLog::getPercent() {
169
if(seekable) return ((SeekLog*)logf)->getPercent();
174
bool RCommitLog::findNextCommit(RCommit& commit, int attempts) {
176
for(int i=0;i<attempts;i++) {
188
bool RCommitLog::nextCommit(RCommit& commit) {
196
bool success = parseCommit(commit);
198
if(!success) return false;
200
return commit.isValid();
203
bool RCommitLog::isFinished() {
204
if(seekable && logf->isFinished()) return true;
210
void RCommitLog::createTempLog() {
215
DWORD tmplen = GetTempPath(0, "");
217
if(tmplen == 0) return;
219
std::vector<TCHAR> temp(tmplen+1);
221
tmplen = GetTempPath(static_cast<DWORD>(temp.size()), &temp[0]);
223
if(tmplen == 0 || tmplen >= temp.size()) return;
225
tempdir = std::string(temp.begin(), temp.begin() + static_cast<std::size_t>(tmplen));
232
snprintf(tmplate, 1024, "%sgource-XXXXXX", tempdir.c_str());
235
if(mktemp(tmplate) < 0) return;
237
if(mkstemp(tmplate) < 0) return;
240
temp_file = std::string(tmplate);
245
RCommitFile::RCommitFile(const std::string& filename, const std::string& action, vec3f colour) {
247
this->filename = munge_utf8(filename);
249
//prepend a root slash
250
if(this->filename[0] != '/') {
251
this->filename.insert(0, 1, '/');
254
this->action = action;
255
this->colour = colour;
262
vec3f RCommit::fileColour(const std::string& filename) {
264
size_t slash = filename.rfind('/');
265
size_t dot = filename.rfind('.');
267
if(dot != std::string::npos && dot+1<filename.size() && (slash == std::string::npos || slash < dot)) {
268
std::string file_ext = filename.substr(dot+1);
270
return colourHash(file_ext);
272
return vec3f(1.0, 1.0, 1.0);
276
void RCommit::addFile(const std::string& filename, const std::string& action) {
277
files.push_back(RCommitFile(filename, action, fileColour(filename)));
280
void RCommit::addFile(const std::string& filename, const std::string& action, vec3f colour) {
281
files.push_back(RCommitFile(filename, action, colour));
284
bool RCommit::isValid() {
286
username = munge_utf8(username);
291
void RCommit::debug() {
292
debugLog("files:\n");
294
for(std::list<RCommitFile>::iterator it = files.begin(); it != files.end(); it++) {
296
debugLog("%s %s\n", f.action.c_str(), f.filename.c_str());