diff --git a/media/css/main.css b/media/css/main.css index b1a7826..1332236 100644 --- a/media/css/main.css +++ b/media/css/main.css @@ -1,4 +1,14 @@ +body { + font-family: Helvetica,Arial,sans-serif; +} + +td { + border-right: 1px #ddd solid; + border-bottom: 1px #888 solid; + padding: 0.6ex; +} + #body { padding: 1ex; } @@ -47,6 +57,10 @@ ul.menu li { margin-right: 1ex; } +.block-last_comments ul { + padding-left: 1em; +} + .comment { border-top: 1px #888 solid; margin-bottom: 1em; diff --git a/mgmt/rights.py b/mgmt/rights.py index 2e8de01..567f774 100644 --- a/mgmt/rights.py +++ b/mgmt/rights.py @@ -26,8 +26,6 @@ def can_change_bug_state(user,bug,new_state): def can(user,action,object=None,target=None): if action in ['comment','send bug']: return user.is_authenticated() -# if action in ['create', 'edit', 'delete']: -# return user.is_authenticated() and user.has_perm('mgmt.%s.%s' % (object,action)) if action == 'edit': if object.__class__.__name__ == 'Project': return user in object.admins.iterator() diff --git a/pygit/__init__.py b/pygit/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pygit/models.py b/pygit/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/pygit/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/pygit/pygit.py b/pygit/pygit.py new file mode 100644 index 0000000..8d2cca9 --- /dev/null +++ b/pygit/pygit.py @@ -0,0 +1,83 @@ + +from os.path import basename +from git import * + +REPOS = ['/home/portnov/www/projects'] + +rp = None +curr_path = None + +def open_repo(rid): + global curr_path,rp + path = REPOS[int(rid)] + if rp and curr_path==path: + return rp + curr_path = path + rp = Repo(path) + return rp + +def files(tree): + contents = tree.contents + return [(blob.id,blob.name) for blob in contents if blob.__class__.__name__=='Blob'] + +def dirs(tree): + contents = tree.contents + return [(tree.id,tree.name) for tree in contents if tree.__class__.__name__=='Tree'] + +def repos(): + return [(i,basename(REPOS[i])) for i in range(len(REPOS))] + +def description(rid): + r = open_repo(rid) + return r.description + +def branches(rid): + r = open_repo(rid) + return [b.name for b in r.branches] + +def date(tp): + y,m,d,h,M,s,_,_,_ = tp + return "%d.%d.%d %d:%d:%d" % (d,m,y,h,M,s) + +def commits(rid,branch='master'): + r = open_repo(rid) + cs = r.commits(branch)[:20] + return [(c.id_abbrev,date(c.authored_date),c.author.name,c.message) for c in cs] + +def root_tree(rid,branch='master'): + r = open_repo(rid) + t = r.tree() + ds = dirs(t) + fs = files(t) + return ds,fs + +def tree(rid,tid): + r = open_repo(rid) + t = r.tree(tid) + return dirs(t),files(t) + +def blame(rid,file,branch='master'): + r = open_repo(rid) + bl = Blob.blame(r,branch,file) + return [(ci.id_abbrev,ci.author.name,date(ci.authored_date),ci.message[:40],''.join(l[:40])) for ci,l in bl] + +def diff_all(rid,cid1,cid2=None): + r = open_repo(rid) + c1 = r.commits(cid1)[0] + if cid2: + c2 = r.commits(cid2)[0] + else: + c2 = c1.parents[0] + ds = Commit.diff(r,c1,c2) + return [(d.a_path,d.diff) for d in ds] + +def diff_path(rid,path,cid1,cid2=None): + r = open_repo(rid) + c1 = r.commits(cid1)[0] + if cid2: + c2 = r.commits(cid2)[0] + else: + c2 = c1.parents[0] + ds = Commit.diff(r,c1,c2) + return [(d.a_path,d.diff) for d in ds if d.a_path==path] + diff --git a/pygit/views.py b/pygit/views.py new file mode 100644 index 0000000..5070df5 --- /dev/null +++ b/pygit/views.py @@ -0,0 +1,58 @@ +# Create your views here. + +import sys +from os.path import dirname,join + +import pygit + +sys.path.append(dirname(dirname(__file__))) +from mgmt.views import render_it + +def all_repos(request): + return render_it('repos.html', + {'repos': pygit.repos()}, + request) + +def one_repo(request,rid,branch='master'): + dsc = pygit.description(rid) + brs = pygit.branches(rid) + cs = pygit.commits(rid,branch) + dirs,files = pygit.root_tree(rid,branch) + return render_it('repo.html', + {'description': dsc, + 'rid': rid, + 'current_branch': branch, + 'branches': brs, + 'commits': cs, + 'dirs': dirs, + 'files': files}, + request) + +def tree(request,rid,branch,tid,path): + dirs,files = pygit.tree(rid,tid) + return render_it('git_tree.html', + {'rid': rid, + 'branch': branch, + 'path': path, + 'dirs': dirs, + 'files': files}, + request) + +def blame(request,rid,branch,path): + bl = pygit.blame(rid,path,branch) + return render_it('git_blame.html', + {'rid': rid, + 'path': path, + 'blame': bl}, + request) + +def diff(request,rid,cid,path=None): + if not path: + ds = pygit.diff_all(rid,cid) + else: + ds = pygit.diff_path(rid,path,cid) + return render_it('git_diff.html', + {'path': path, + 'cid': cid, + 'diffs': ds}, + request) diff --git a/templates/comments.html b/templates/comments.html index 3ba70a4..3408519 100644 --- a/templates/comments.html +++ b/templates/comments.html @@ -3,6 +3,7 @@ <div class='comments'> {% for comment in comments %} <div class='comment'> + <a name='comment-{{comment.id}}' /> <p class='comment-title'>{{ comment.title }} от {{ comment.author }}, {{ comment.created }}</p> <p>{{ comment.text }}</p> </div> diff --git a/templates/git_blame.html b/templates/git_blame.html new file mode 100644 index 0000000..3d0f7ea --- /dev/null +++ b/templates/git_blame.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block title %}История файла {{path}}{% endblock %} + +{% block main %} +<h2>История файла {{path}}</h2> + +<table> + {% for cid,author,dt,message,line in blame %} + <tr> + <td><a href='/git/diff/{{rid}}/{{cid}}/{{path}}/'>{{cid}}</a></td> + <td>{{author}}</td><td>{{dt}}</td><td>{{message}}</td><td>{{forloop.counter}}</td><td>{{line}}</td> + </tr> + {% endfor %} +</table> + +{% endblock %} diff --git a/templates/git_diff.html b/templates/git_diff.html new file mode 100644 index 0000000..0963758 --- /dev/null +++ b/templates/git_diff.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{% block title %}Diff: #{{cid}}{% if path %} {{path}}{% endif %}{% endblock %} + +{% block main %} + +<h2>Diff: #{{cid}}{% if path %} {{path}}{% endif %}</h2> +{% for file,diff in diffs %} + <h3>{{file}}</h3> + <code><pre> + {{diff}} + </pre></code> +{% endfor %} + +{% endblock %} diff --git a/templates/git_tree.html b/templates/git_tree.html new file mode 100644 index 0000000..82a75f1 --- /dev/null +++ b/templates/git_tree.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block title %}Список файлов{% endblock %} + +{% block main %} +<h3>Файлы:</h3> + +<ul> + {% for id,name in dirs %} + <li><a href='/git/repo/{{rid}}/{{branch}}/tree/{{id}}/{{path}}/{{name}}/'>{{name}}</a></li> + {% endfor %} + {% for id,name in files %} + <li><a href='/git/blame/{{rid}}/{{branch}}/{{path}}/{{name}}/'>{{name}}</a></li> + {% endfor %} +</ul> + +{% endblock %} diff --git a/templates/repo.html b/templates/repo.html new file mode 100644 index 0000000..5825391 --- /dev/null +++ b/templates/repo.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} + +{% block title %}Репозиторий: {{description}}{% endblock %} + +{% block main %} + +<h2>Репозиторий: {{description}}</h2> + +<div class='links'> + Ветви: + {% for branch in branches %} + <a href='/git/repo/{{rid}}/{{branch}}/'>{{branch}}</a> + {% endfor %} +</div> + +<h3>Последние коммиты:</h3> + +<table> + {% for id,dt,author,message in commits %} + <tr> + <td><a href='/git/diff/{{rid}}/{{id}}/'>{{id}}</a></td><td>{{dt}}</td><td>{{author}}</td><td>{{message}}</td> + </tr> + {% endfor %} +</table> + +<h3>Файлы:</h3> + +<ul> + {% for id,name in dirs %} + <li><a href='/git/repo/{{rid}}/{{current_branch}}/tree/{{id}}/{{name}}/'>{{name}}</a></li> + {% endfor %} + {% for id,name in files %} + <li><a href='/git/blame/{{rid}}/{{current_branch}}/{{name}}/'>{{name}}</a></li> + {% endfor %} +</ul> + +{% endblock %} diff --git a/templates/repos.html b/templates/repos.html new file mode 100644 index 0000000..c4e278f --- /dev/null +++ b/templates/repos.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{%block title%}Список репозиториев Git{% endblock %} + +{% block main %} + +<h2>Список репозиториев Git</h2> + +<ul> + {% for id,name in repos %} + <li><a href='/git/repo/{{id}}/'>{{name}}</a></li> + {% endfor %} +</ul> + +{% endblock %} diff --git a/urls.py b/urls.py index 0f8f5a4..360867a 100644 --- a/urls.py +++ b/urls.py @@ -12,6 +12,13 @@ urlpatterns = patterns('', (r'^bugs/(\d+)/edit/$', "mgmt.views.edit_bug"), (r'^bugs/$', "mgmt.views.all_bugs"), (r'^create/doc/(\d+)/$', "mgmt.views.create_document"), + (r'^git/$', "pygit.views.all_repos"), + (r'^git/repo/(\d+)/$', 'pygit.views.one_repo'), + (r'^git/repo/(\d+)/(\w+)/$', 'pygit.views.one_repo'), + (r'^git/repo/(\d+)/(\w+)/tree/(\w+)/(.*)/$', 'pygit.views.tree'), + (r'^git/blame/(\d+)/(\w+)/(.*)/$','pygit.views.blame'), + (r'^git/diff/(\d+)/(\w+)/$', 'pygit.views.diff'), + (r'^git/diff/(\d+)/(\w+)/(.*)/$', 'pygit.views.diff'), (r'^login/', login), (r'^logout/', logout),