Skip to content

Commit

Permalink
Merge branch 'master' of github.com:acaudwell/Gource
Browse files Browse the repository at this point in the history
  • Loading branch information
acaudwell committed Dec 10, 2009
2 parents e706fba + fd3cf51 commit 3c95836
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 4 deletions.
3 changes: 3 additions & 0 deletions README
Expand Up @@ -262,6 +262,9 @@ with the Code Blocks IDE (www.codeblocks.org).
6. Changes
==========

0.19:
* Use time_t instead of long for timestamps.

0.18:
* Fixed camera movement while the simulation is paused.

Expand Down
108 changes: 108 additions & 0 deletions contrib/mercurial-gource.py
@@ -0,0 +1,108 @@
#!/usr/bin/env python

# python script to parse the mercurial repository log into the custom format
# expected by Gource (http://code.google.com/p/gource/)
# Gource is a software version control visualization program, pretty cool :)
#
# usage:
# ./mercurial-gource.py [OUTPUT_FILE]
#
# where:
# OUTPUT_FILE is the output file for the custom log
# if OUTPUT_FILE is not provided, output to stdout
#
# example usage with Gource (assuming that Gource is installed):
# ./mercurial-gource.py project.log && gource project.log
# OR
# ./mercurial-gource.py | gource --log-format custom -
# but gource doesn't loop at the end when reading from stdin
#
#
# This script should work for any mercurial repository (version number?),
#
# Something that may be worth doing is adding a "--limit NUMBER" to hg log,
# where NUMBER is an argument to this script?
#


def custom_logformat(date, author, type, file):
return '%(date)s|%(author)s|%(type)s|%(file)s' %{
'date': date,
'author': author,
'type': type,
'file': file,
}


if __name__ == '__main__':
import subprocess
# get the log, in a easy to parse format
args = ['hg', 'log', '--template', '{date}|{author|person}|m {files}|a {file_adds}|d {file_dels}\n']
process = subprocess.Popen(args, stdout=subprocess.PIPE)
log_output, log_err = process.communicate()
entries = log_output.split('\n')

# regex used to parse the hg log
import re
custom_regex = r'([0-9.+-]+)\|([^|]+)\|m ([^|]+)?\|a ([^|]+)?\|d ([^|]+)?'
regex = re.compile(custom_regex)

# get the output (file or stdout)
import sys
outfile = None
if len(sys.argv) == 2:
outfile = open(sys.argv[1], 'w')
else:
outfile = sys.stdout

# important fields of log
date = ''
author = ''
# mercurial doesn't seem to have a 'file_modifies' template keyword, but
# there is a 'files' template keyword, which includes:
# modified, added and removed
# so: modfied = files - added - removed
modified = []
added = []
deleted = []

# hg log lists newest to oldest, gource wants oldest to newest
# so just reverse the entries
entries.reverse()
for entry in entries:
if entry == '':
continue

match = regex.match(entry)
if not match:
# sys.stderr.write('** Non-matching: %s\n' %entry)
continue

date, author, modified, added, deleted = match.groups()
# dunno if this is the best way of parsing the timestamp, which should be
# in the format: {UTC timestamp}{timezone offset}
# e.g. 1234567890.0-7200
date = str(int(eval(date)))

modified = modified.split() if modified else []
added = added.split() if added else []
deleted = deleted.split() if deleted else []

for f in added:
outfile.write(custom_logformat(date, author, 'A', f))
outfile.write('\n')
if f in modified:
modified.remove(f)

for f in deleted:
outfile.write(custom_logformat(date, author, 'D', f))
outfile.write('\n')
if f in modified:
modified.remove(f)

for f in modified:
outfile.write(custom_logformat(date, author, 'M', f))
outfile.write('\n')

outfile.close()

109 changes: 109 additions & 0 deletions contrib/svn-gource.py
@@ -0,0 +1,109 @@
#!/usr/bin/python
## Copyright (c) 2009 Cameron Hart (cam@bitshifter.net.nz)
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## 1. Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## 2. Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## 3. The name of the author may not be used to endorse or promote products
## derived from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
## IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
## OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
## IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
## INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
## THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import sys
import time
import getopt
import re
from xml.etree import ElementTree

opt_filter_dirs = False

_USAGE = """
svn-gource.py [--help] [--filter-dirs] <file>
The input file must be the output of the command svn log --verbose --xml.
"""

# regular expression for matching any file with an extension
extn_prog = re.compile(".*/?[^/]+\.[^\.]+$")

def reverse(data):
"""Returns the log entries in reverse."""
for index in range(len(data)-1, -1, -1):
yield data[index]

def processXmltree(xmltree):
global opt_filter_dirs
for logentry in reverse(xmltree.getiterator("logentry")):
datetext = logentry.find("date").text

# svn xml logs always use UTC
timestamp = (time.mktime(time.strptime(datetext[:-8], "%Y-%m-%dT%H:%M:%S")))
# a bit of a hack to get it into local time again...
#timestamp = timestamp - time.timezone

#author might not exist
try:
author = logentry.find("author").text
except:
author = ""

# output all affected files
for pathentry in logentry.getiterator("path"):

# apply directory filtering strategy
if opt_filter_dirs and not re.match(extn_prog, pathentry.text):
continue;

# join output
print "|".join( ("%d" % int(timestamp), author.encode("utf-8"), pathentry.get("action"), pathentry.text.encode("utf-8"), "") )

def printUsage(message):
sys.stderr.write(_USAGE)
if message:
sys.exit('\nFATAL ERROR: ' + message)
else:
sys.exit(1)

def processArguments():
global opt_filter_dirs

try:
opts, filenames = getopt.getopt(sys.argv[1:], '', ['help', 'filter-dirs'])
except getopt.GetoptError:
printUsage('Invalid arguments.')

for (opt, val) in opts:
if opt == '--help':
printUsage(None)
elif opt == '--filter-dirs':
opt_filter_dirs = True

if not filenames:
printUsage('No input file specified.')

return filenames[0]


if __name__ == "__main__":
filename = processArguments()

xmltree = ElementTree.parse(filename)

processXmltree(xmltree)



1 change: 1 addition & 0 deletions dev/bin/build_tar.pl
Expand Up @@ -22,6 +22,7 @@ sub gource_version {
my $VERSION = gource_version();

my @exclusions = (
qr{^/contrib/},
qr{^/config.status$},
qr{^/config.log$},
qr{^/debian/},
Expand Down
2 changes: 1 addition & 1 deletion src/commitlog.h
Expand Up @@ -42,7 +42,7 @@ class RCommitFile {
class RCommit {
vec3f fileColour(std::string filename);
public:
long timestamp;
time_t timestamp;
std::string username;

std::list<RCommitFile> files;
Expand Down
2 changes: 1 addition & 1 deletion src/gource.cpp
Expand Up @@ -1319,7 +1319,7 @@ void Gource::logic(float t, float dt) {
subseconds -= (int) subseconds;
}

currtime += seconds;
currtime += seconds;

// delete files
for(std::vector<RFile*>::iterator it = gGourceRemovedFiles.begin(); it != gGourceRemovedFiles.end(); it++) {
Expand Down
4 changes: 2 additions & 2 deletions src/gource.h
Expand Up @@ -18,7 +18,7 @@
#ifndef GOURCE_H
#define GOURCE_H

#define GOURCE_VERSION "0.18"
#define GOURCE_VERSION "0.19"

#ifdef _WIN32
#include "windows.h"
Expand Down Expand Up @@ -111,8 +111,8 @@ class Gource : public SDLApp {
int frameskip;
int framecount;

time_t currtime;
float runtime;
long currtime;
float subseconds;

float splash;
Expand Down

0 comments on commit 3c95836

Please sign in to comment.