mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-03 07:55:36 +00:00
View repo history directory.
This commit is contained in:
@@ -14,7 +14,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th width="20%">修改时间</th>
|
<th width="20%">修改时间</th>
|
||||||
<th width="10%">修改者</th>
|
<th width="10%">修改者</th>
|
||||||
<th width="70%">描述</th>
|
<th width="60%">描述</th>
|
||||||
|
<th width="10%">操作</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for commit in commits %}
|
{% for commit in commits %}
|
||||||
<tr>
|
<tr>
|
||||||
@@ -25,6 +26,11 @@
|
|||||||
<td>未知</td>
|
<td>未知</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td>{{ commit.props.desc|translate_commit_desc }}</td>
|
<td>{{ commit.props.desc|translate_commit_desc }}</td>
|
||||||
|
{% if not forloop.last %}
|
||||||
|
<td><a href="{{ SITE_ROOT }}repo/history/dir/{{ repo.id }}/?commit_id={{ commit.id }}">浏览</a></td>
|
||||||
|
{% else %}
|
||||||
|
<td></td>
|
||||||
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
79
templates/repo_history_dir.html
Normal file
79
templates/repo_history_dir.html
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
{% extends "myhome_base.html" %}
|
||||||
|
{% load seahub_tags %}
|
||||||
|
|
||||||
|
{% block main_panel %}
|
||||||
|
<div id="repo-page" class="ovhd">
|
||||||
|
<h2>{{repo.props.name}} 历史浏览</h2>
|
||||||
|
<div class="side fright">
|
||||||
|
{% if not repo.props.encrypted %}
|
||||||
|
{% if is_owner or repo_ap == 'public' or share_to_me %}
|
||||||
|
<p class="latest-commit mgt10">
|
||||||
|
{{ current_commit.props.desc|translate_commit_desc }}<br />
|
||||||
|
<span class="author">by
|
||||||
|
{% if current_commit.props.creator_name %}
|
||||||
|
{{ current_commit.props.creator_name }}
|
||||||
|
{% else %}
|
||||||
|
未知
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
<span class="time">{{ current_commit.props.ctime|tsstr_sec }}</span>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
<a href="{{ SITE_ROOT }}repo/history/{{ repo.id }}/"><p>返回历史列表</p></a>
|
||||||
|
</div>
|
||||||
|
<div class="main fleft">
|
||||||
|
{% if repo.props.encrypted %}
|
||||||
|
<p>该同步目录已加密,不能在线查看。</p>
|
||||||
|
{% else %}
|
||||||
|
{% if not is_owner and repo_ap == 'own' and not share_to_me %}
|
||||||
|
<p>该同步目录web匿名访问未开启,不能在线查看。</p>
|
||||||
|
{% else %}
|
||||||
|
<div>
|
||||||
|
{% for name, link in zipped %}
|
||||||
|
{% if not forloop.last %}
|
||||||
|
<a href="{{ SITE_ROOT }}repo/history/dir/{{ repo.id }}/?commit_id={{ current_commit.id}}&p={{ link|urlencode }}">{{ name }}</a> /
|
||||||
|
{% else %}
|
||||||
|
{{ name }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th width="5%"></th>
|
||||||
|
<th width="55%">名字</th>
|
||||||
|
<th width="10%">大小</th>
|
||||||
|
<th width="30%">操作</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% for dirent in dir_list %}
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ MEDIA_URL }}img/folder-icon-24.png" /></td>
|
||||||
|
<td><a href="{{ SITE_ROOT }}repo/history/dir/{{ repo.id }}/?commit_id={{ current_commit.id }}&p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{{ dirent.obj_name }}</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for dirent in file_list %}
|
||||||
|
<tr>
|
||||||
|
<td><img src="{{ MEDIA_URL }}img/{{ dirent.obj_name|file_icon_filter }}" /></td>
|
||||||
|
<td>{{ dirent.props.obj_name }}</td>
|
||||||
|
<td>{{ dirent.file_size|filesizeformat }}</td>
|
||||||
|
<td>
|
||||||
|
<a class="op" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name }}&op=view">查看</a>
|
||||||
|
<a class="op" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name }}&op=download">下载</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_script %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
3
urls.py
3
urls.py
@@ -5,7 +5,7 @@ from django.views.generic.simple import direct_to_template
|
|||||||
from seahub.views import root, peers, myhome, \
|
from seahub.views import root, peers, myhome, \
|
||||||
repo, repo_history, modify_token, remove_repo, seafadmin, useradmin, \
|
repo, repo_history, modify_token, remove_repo, seafadmin, useradmin, \
|
||||||
role_add, role_remove, activate_user, user_add, user_remove, \
|
role_add, role_remove, activate_user, user_add, user_remove, \
|
||||||
ownerhome, remove_fetched_repo, \
|
ownerhome, remove_fetched_repo, repo_history_dir, \
|
||||||
user_info, repo_set_access_property, repo_access_file, \
|
user_info, repo_set_access_property, repo_access_file, \
|
||||||
repo_add_share, repo_list_share, repo_remove_share, repo_download, \
|
repo_add_share, repo_list_share, repo_remove_share, repo_download, \
|
||||||
seafile_access_check, back_local
|
seafile_access_check, back_local
|
||||||
@@ -38,6 +38,7 @@ urlpatterns = patterns('',
|
|||||||
|
|
||||||
(r'^repo/(?P<repo_id>[^/]+)/$', repo),
|
(r'^repo/(?P<repo_id>[^/]+)/$', repo),
|
||||||
(r'^repo/history/(?P<repo_id>[^/]+)/$', repo_history),
|
(r'^repo/history/(?P<repo_id>[^/]+)/$', repo_history),
|
||||||
|
(r'^repo/history/dir/(?P<repo_id>[^/]+)/$', repo_history_dir),
|
||||||
(r'^repo/token/modify/(?P<repo_id>[^/]+)/$', modify_token),
|
(r'^repo/token/modify/(?P<repo_id>[^/]+)/$', modify_token),
|
||||||
(r'^repo/remove/(?P<repo_id>[^/]+)/$', remove_repo),
|
(r'^repo/remove/(?P<repo_id>[^/]+)/$', remove_repo),
|
||||||
(r'^repo/removefetched/(?P<user_id>[^/]+)/(?P<repo_id>[^/]+)/$', remove_fetched_repo),
|
(r'^repo/removefetched/(?P<user_id>[^/]+)/(?P<repo_id>[^/]+)/$', remove_fetched_repo),
|
||||||
|
138
views.py
138
views.py
@@ -92,6 +92,42 @@ def validate_emailuser(emailuser):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def access_to_repo(request, repo_id, repo_ap):
|
||||||
|
"""
|
||||||
|
Check whether user in the request can access to repo, which means user can
|
||||||
|
view directory entries on repo page, and repo_history_dir page.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# if repo is 'own' and user is not staff and is not owner
|
||||||
|
# and not shared this repo, then goto 404 page..
|
||||||
|
if repo_ap == 'own' and not validate_owner(request, repo_id) \
|
||||||
|
and not check_shared_repo(request, repo_id) and not request.user.is_staff:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def gen_path_link(path, repo_name):
|
||||||
|
"""
|
||||||
|
Generate navigate paths and links in repo page and repo_history_dir page.
|
||||||
|
Note: `path` must be end with '/'.
|
||||||
|
|
||||||
|
"""
|
||||||
|
paths = []
|
||||||
|
links = []
|
||||||
|
if path and path != '/':
|
||||||
|
paths = path[1:-1].split('/')
|
||||||
|
i=1
|
||||||
|
for name in paths:
|
||||||
|
link = '/' + '/'.join(paths[:i])
|
||||||
|
i = i + 1
|
||||||
|
links.append(link)
|
||||||
|
paths.insert(0, repo_name)
|
||||||
|
links.insert(0, '/')
|
||||||
|
|
||||||
|
zipped = zip(paths, links)
|
||||||
|
|
||||||
|
return zipped
|
||||||
|
|
||||||
def repo(request, repo_id):
|
def repo(request, repo_id):
|
||||||
# get repo web access property, if no repo access property in db, then
|
# get repo web access property, if no repo access property in db, then
|
||||||
# assume repo ap is 'own'
|
# assume repo ap is 'own'
|
||||||
@@ -99,19 +135,15 @@ def repo(request, repo_id):
|
|||||||
if repo_ap == None:
|
if repo_ap == None:
|
||||||
repo_ap = 'own'
|
repo_ap = 'own'
|
||||||
|
|
||||||
# if repo is 'own' and user is not staff and is not owner
|
if not access_to_repo(request, repo_id, repo_ap):
|
||||||
# and not shared this repo, then goto 404 page..
|
|
||||||
if cmp(repo_ap, 'own') == 0 and not validate_owner(request, repo_id) \
|
|
||||||
and not check_shared_repo(request, repo_id) and not request.user.is_staff:
|
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
repo = get_repo(repo_id)
|
repo = get_repo(repo_id)
|
||||||
if repo == None:
|
if not repo:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
latest_commit = get_commits(repo_id, 0, 1)[0]
|
latest_commit = get_commits(repo_id, 0, 1)[0]
|
||||||
|
|
||||||
token = ""
|
|
||||||
is_owner = False
|
is_owner = False
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
if validate_owner(request, repo_id):
|
if validate_owner(request, repo_id):
|
||||||
@@ -119,20 +151,19 @@ def repo(request, repo_id):
|
|||||||
|
|
||||||
repo_size = seafserv_threaded_rpc.server_repo_size(repo_id)
|
repo_size = seafserv_threaded_rpc.server_repo_size(repo_id)
|
||||||
|
|
||||||
latest_commit = {}
|
|
||||||
dirs = []
|
dirs = []
|
||||||
path = ''
|
path = ''
|
||||||
zipped = []
|
zipped = []
|
||||||
dir_list = []
|
dir_list = []
|
||||||
file_list = []
|
file_list = []
|
||||||
if not repo.props.encrypted:
|
if not repo.props.encrypted:
|
||||||
latest_commit = get_commits(repo_id, 0, 1)[0]
|
|
||||||
path = request.GET.get('p', '/')
|
path = request.GET.get('p', '/')
|
||||||
if path[-1] != '/':
|
if path[-1] != '/':
|
||||||
path = path + '/'
|
path = path + '/'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dirs = seafserv_rpc.list_dir_by_path(latest_commit.id, path.encode('utf-8'))
|
dirs = seafserv_rpc.list_dir_by_path(latest_commit.id,
|
||||||
|
path.encode('utf-8'))
|
||||||
except SearpcError, e:
|
except SearpcError, e:
|
||||||
return go_error(request, e.msg)
|
return go_error(request, e.msg)
|
||||||
for dirent in dirs:
|
for dirent in dirs:
|
||||||
@@ -148,20 +179,8 @@ def repo(request, repo_id):
|
|||||||
file_list.sort(lambda x, y : cmp(x.obj_name.lower(), y.obj_name.lower()))
|
file_list.sort(lambda x, y : cmp(x.obj_name.lower(), y.obj_name.lower()))
|
||||||
|
|
||||||
# generate path and link
|
# generate path and link
|
||||||
paths = []
|
zipped = gen_path_link(path, repo.name)
|
||||||
links = []
|
|
||||||
if path and path != '/':
|
|
||||||
paths = path[1:-1].split('/')
|
|
||||||
i=1
|
|
||||||
for name in paths:
|
|
||||||
link = '/' + '/'.join(paths[:i])
|
|
||||||
i = i + 1
|
|
||||||
links.append(link)
|
|
||||||
paths.insert(0, repo.name)
|
|
||||||
links.insert(0, '/')
|
|
||||||
|
|
||||||
zipped = zip(paths, links)
|
|
||||||
|
|
||||||
# used to determin whether show repo content in repo.html
|
# used to determin whether show repo content in repo.html
|
||||||
# if a repo is shared to me, or repo shared to the group I joined,
|
# if a repo is shared to me, or repo shared to the group I joined,
|
||||||
# then I can view repo content on the web
|
# then I can view repo content on the web
|
||||||
@@ -213,7 +232,81 @@ def repo_history(request, repo_id):
|
|||||||
'page_next': page_next,
|
'page_next': page_next,
|
||||||
}, context_instance=RequestContext(request))
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
def repo_history_dir(request, repo_id):
|
||||||
|
# get repo web access property, if no repo access property in db, then
|
||||||
|
# assume repo ap is 'own'
|
||||||
|
repo_ap = seafserv_threaded_rpc.repo_query_access_property(repo_id)
|
||||||
|
if repo_ap == None:
|
||||||
|
repo_ap = 'own'
|
||||||
|
|
||||||
|
if not access_to_repo(request, repo_id, repo_ap):
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
repo = get_repo(repo_id)
|
||||||
|
if not repo:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
current_commit = None
|
||||||
|
commit_id = request.GET.get('commit_id', None)
|
||||||
|
if commit_id:
|
||||||
|
current_commit = seafserv_rpc.get_commit(commit_id)
|
||||||
|
if not current_commit:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
is_owner = False
|
||||||
|
if request.user.is_authenticated():
|
||||||
|
if validate_owner(request, repo_id):
|
||||||
|
is_owner = True
|
||||||
|
|
||||||
|
dirs = []
|
||||||
|
path = ''
|
||||||
|
zipped = []
|
||||||
|
dir_list = []
|
||||||
|
file_list = []
|
||||||
|
if not repo.props.encrypted:
|
||||||
|
path = request.GET.get('p', '/')
|
||||||
|
if path[-1] != '/':
|
||||||
|
path = path + '/'
|
||||||
|
try:
|
||||||
|
dirs = seafserv_rpc.list_dir_by_path(current_commit.id,
|
||||||
|
path.encode('utf-8'))
|
||||||
|
except SearpcError, e:
|
||||||
|
return go_error(request, e.msg)
|
||||||
|
for dirent in dirs:
|
||||||
|
if stat.S_ISDIR(dirent.props.mode):
|
||||||
|
dir_list.append(dirent)
|
||||||
|
else:
|
||||||
|
file_list.append(dirent)
|
||||||
|
try:
|
||||||
|
dirent.file_size = seafserv_rpc.get_file_size(dirent.obj_id)
|
||||||
|
except:
|
||||||
|
dirent.file_size = 0
|
||||||
|
dir_list.sort(lambda x, y : cmp(x.obj_name.lower(), y.obj_name.lower()))
|
||||||
|
file_list.sort(lambda x, y : cmp(x.obj_name.lower(), y.obj_name.lower()))
|
||||||
|
|
||||||
|
# generate path and link
|
||||||
|
zipped = gen_path_link(path, repo.name)
|
||||||
|
|
||||||
|
# used to determin whether show repo content in repo.html
|
||||||
|
# if a repo is shared to me, or repo shared to the group I joined,
|
||||||
|
# then I can view repo content on the web
|
||||||
|
if check_shared_repo(request, repo_id):
|
||||||
|
share_to_me = True
|
||||||
|
else:
|
||||||
|
share_to_me = False
|
||||||
|
|
||||||
|
return render_to_response('repo_history_dir.html', {
|
||||||
|
"repo": repo,
|
||||||
|
"current_commit": current_commit,
|
||||||
|
"is_owner": is_owner,
|
||||||
|
"repo_ap": repo_ap,
|
||||||
|
"dir_list": dir_list,
|
||||||
|
"file_list": file_list,
|
||||||
|
"share_to_me": share_to_me,
|
||||||
|
"path" : path,
|
||||||
|
"zipped" : zipped,
|
||||||
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def modify_token(request, repo_id):
|
def modify_token(request, repo_id):
|
||||||
if not validate_owner(request, repo_id):
|
if not validate_owner(request, repo_id):
|
||||||
@@ -225,7 +318,6 @@ def modify_token(request, repo_id):
|
|||||||
|
|
||||||
return HttpResponseRedirect(reverse(repo, args=[repo_id]))
|
return HttpResponseRedirect(reverse(repo, args=[repo_id]))
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def remove_repo(request, repo_id):
|
def remove_repo(request, repo_id):
|
||||||
if not validate_owner(request, repo_id) and not request.user.is_staff:
|
if not validate_owner(request, repo_id) and not request.user.is_staff:
|
||||||
|
Reference in New Issue
Block a user