~ubuntu-branches/debian/wheezy/gource/wheezy

« back to all changes in this revision

Viewing changes to src/git.cpp

  • Committer: Package Import Robot
  • Author(s): Andrew Caudwell
  • Date: 2012-04-24 11:25:45 UTC
  • mfrom: (1.2.13)
  • Revision ID: package-import@ubuntu.com-20120424112545-18fbnycu9xrsl4s5
Tags: 0.38-1
* New upstream release (closes: #667189)
* New build dependencies on libglm-dev and libboost-filesystem-dev. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
    Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.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 "git.h"
19
 
 
20
 
// parse git log entries
21
 
 
22
 
//git-log command notes:
23
 
// - no single quotes on WIN32 as system call treats them differently
24
 
// - 'user:' prefix allows us to quickly tell if the log is the wrong format
25
 
//   and try a different format (eg cvs-exp)
26
 
 
27
 
std::string gGourceGitLogCommand = "git log "
28
 
    "--pretty=format:user:%aN%n%ct "
29
 
    "--reverse --raw --encoding=UTF-8 "
30
 
    "--no-renames";
31
 
 
32
 
GitCommitLog::GitCommitLog(const std::string& logfile) : RCommitLog(logfile, 'u') {
33
 
 
34
 
    log_command = gGourceGitLogCommand;
35
 
 
36
 
    if(gGourceSettings.git_branch.size()>0) {
37
 
        log_command += " ";
38
 
        log_command += gGourceSettings.git_branch;
39
 
    }
40
 
 
41
 
    //can generate log from directory
42
 
    if(!logf && is_dir) {
43
 
        logf = generateLog(logfile);
44
 
 
45
 
        if(logf) {
46
 
            success  = true;
47
 
            seekable = true;
48
 
        }
49
 
    }
50
 
}
51
 
 
52
 
BaseLog* GitCommitLog::generateLog(const std::string& dir) {
53
 
    //get working directory
54
 
    char cwd_buff[1024];
55
 
 
56
 
    if(getcwd(cwd_buff, 1024) != cwd_buff) {
57
 
        return 0;
58
 
    }
59
 
 
60
 
    //does directory have a .git ?
61
 
    std::string gitdir = dir + std::string("/.git");
62
 
    struct stat dirinfo;
63
 
    int stat_rc = stat(gitdir.c_str(), &dirinfo);
64
 
    if(stat_rc!=0 || !(dirinfo.st_mode & S_IFDIR)) {
65
 
        return 0;
66
 
    }
67
 
 
68
 
    std::string command = getLogCommand();
69
 
 
70
 
    //create temp file
71
 
    createTempLog();
72
 
 
73
 
    if(temp_file.size()==0) return 0;
74
 
 
75
 
    if(chdir(dir.c_str()) != 0) {
76
 
        return 0;
77
 
    }
78
 
 
79
 
    char cmd_buff[2048];
80
 
    sprintf(cmd_buff, "%s > %s", command.c_str(), temp_file.c_str());
81
 
 
82
 
    int command_rc = system(cmd_buff);
83
 
 
84
 
    if(command_rc != 0) {
85
 
        chdir(cwd_buff);
86
 
        return 0;
87
 
    }
88
 
 
89
 
    // check for new-enough Git version
90
 
    // if %aN does not appear to be supported try %an
91
 
    std::ifstream in(temp_file.c_str());
92
 
    char firstBytes[9];
93
 
    in.read(firstBytes, 8);
94
 
    in.close();
95
 
    firstBytes[8] = '\0';
96
 
    if(!strcmp(firstBytes, "user:%aN")) {
97
 
        char *pos = strstr(cmd_buff, "%aN");
98
 
        pos[2] = 'n';
99
 
        command_rc = system(cmd_buff);
100
 
    }
101
 
 
102
 
    //change back to original directoy
103
 
    chdir(cwd_buff);
104
 
 
105
 
    if(command_rc != 0) {
106
 
        return 0;
107
 
    }
108
 
 
109
 
    BaseLog* seeklog = new SeekLog(temp_file);
110
 
 
111
 
    return seeklog;
112
 
}
113
 
 
114
 
// parse modified git format log entries
115
 
 
116
 
bool GitCommitLog::parseCommit(RCommit& commit) {
117
 
 
118
 
    std::string line;
119
 
 
120
 
    commit.username = "";
121
 
 
122
 
    while(logf->getNextLine(line) && line.size()) {
123
 
 
124
 
        if(line.find("user:") == 0) {
125
 
 
126
 
            //username follows user prefix
127
 
            commit.username = line.substr(5);
128
 
 
129
 
            if(!logf->getNextLine(line)) return false;
130
 
 
131
 
            commit.timestamp = atol(line.c_str());
132
 
 
133
 
            //this isnt a commit we are parsing, abort
134
 
            if(commit.timestamp == 0) return false;
135
 
 
136
 
            continue;
137
 
        }
138
 
 
139
 
        //should see username before files
140
 
        if(commit.username.size() == 0) return false;
141
 
 
142
 
        size_t tab = line.find('\t');
143
 
 
144
 
        //incorrect log format
145
 
        if(tab == std::string::npos || tab == 0 || tab == line.size()-1) continue;
146
 
 
147
 
        std::string status = line.substr(tab - 1, 1);
148
 
        std::string file   = line.substr(tab + 1);
149
 
 
150
 
        if(file.empty()) continue;
151
 
 
152
 
        //check for and remove double quotes
153
 
        if(file.find('"') == 0 && file.rfind('"') == file.size()-1) {
154
 
            if(file.size()<=2) continue;
155
 
 
156
 
            file = file.substr(1,file.size()-2);
157
 
        }
158
 
 
159
 
        commit.addFile(file, status);
160
 
    }
161
 
 
162
 
    //check we at least got a username
163
 
    if(commit.username.size()==0) return false;
164
 
 
165
 
    return true;
166
 
}