1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-09 02:42:47 +00:00

add 'list file history' and 'revert file'

This commit is contained in:
lins05
2012-07-13 17:19:44 +08:00
parent af5575c4a6
commit 2b72bd7213
7 changed files with 210 additions and 17 deletions

View File

@@ -35,8 +35,12 @@ def file_icon_filter(value):
@register.filter(name='translate_commit_desc') @register.filter(name='translate_commit_desc')
def translate_commit_desc(value): def translate_commit_desc(value):
"""Translate commit description.""" """Translate commit description."""
if value.startswith('Reverted'): if value.startswith('Reverted repo'):
return value.replace('Reverted repo to status at', u'同步目录内容还原到') return value.replace('Reverted repo to status at', u'同步目录内容还原到')
elif value.startswith('Reverted file'):
value = value.replace('Reverted file', u'还原文件')
value = value.replace('to status at', u'内容到')
return value
elif value.startswith('Merged'): elif value.startswith('Merged'):
return u'合并了其他人的修改' return u'合并了其他人的修改'
else: else:

View File

@@ -0,0 +1,59 @@
{% extends "myhome_base.html" %}
{% load seahub_tags %}
{% block info_bar_message %}
{% if request.user.is_authenticated %}
{{ block.super }}
{% else %}
<div id="info-bar">
<span class="info">当前链接会在短期内失效,欢迎您 <a href="http://seafile.com/" target="_blank">加入Seafile </a>体验更多功能。</span>
</div>
{% endif %}
{% endblock %}
{% block main_panel %}
<h2>文件修改历史</h2>
<h3 class="file-revisions"><span class="file-name">{{ repo.props.name }} {{path}}</span></h3>
<table>
<tr>
<th width="30%">修改时间</th>
<th width="20%">修改者</th>
<th width="20%">大小</th>
<th width="30%">操作</th>
</tr>
{% for commit in commits %}
<tr>
<td>
{{ commit.props.ctime|tsstr_sec }}
{% if commit.is_current_version %}
(当前版本)
{% endif %}
</td>
{% if commit.props.creator_name %}
<td>{{ commit.props.creator_name }}</td>
{% else %}
<td>未知</td>
{% endif %}
<td>{{ commit.revision_file_size|filesizeformat }} </td>
<td>
{% if not forloop.first %}
{% if is_owner %}
<a href="{{ SITE_ROOT }}repo/file_revisions/{{ repo.id }}/?commit={{ commit.id }}&p={{path|urlencode}}&op=revert" class="file-revert op">还原</a>
{% endif %}
{% endif %}
<a href="{{ SITE_ROOT }}repo/file_revisions/{{ repo.id }}/?commit={{ commit.id }}&p={{path|urlencode}}&op=download" class="file-download op">下载</a>
<a href="{{ SITE_ROOT }}repo/file_revisions/{{ repo.id }}/?commit={{ commit.id }}&p={{path|urlencode}}&op=view" class="file-download op">查看</a>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}
{% block extra_script %}
<script type="text/javascript">
</script>
{% endblock %}

View File

@@ -109,7 +109,7 @@
</p> </p>
{% if not view_history and request.user.is_authenticated %} {% if not view_history and request.user.is_authenticated %}
<div class="repo-op fright"> <div class="repo-op fright">
<a href="{{ SITE_ROOT }}repo/upload_file/{{repo.id}}/?p={{ path }}" class="upload-file">上传</a> <a href="{{ SITE_ROOT }}repo/upload_file/{{repo.id}}/?p={{ path|urlencode }}" class="upload-file">上传</a>
<a id="add-new-dir" href="#">新建目录</a> <a id="add-new-dir" href="#">新建目录</a>
</div> </div>
{% endif %} {% endif %}
@@ -169,7 +169,8 @@
<li><a class="op file-rename" href="#" data="{{ dirent.obj_name }}">重命名</a></li> <li><a class="op file-rename" href="#" data="{{ dirent.obj_name }}">重命名</a></li>
<li><a class="op file-mv" href="#" data="{{ dirent.obj_name }}">移动</a></li> <li><a class="op file-mv" href="#" data="{{ dirent.obj_name }}">移动</a></li>
<li><a class="op file-cp" href="#" data="{{ dirent.obj_name }}">复制</a></li> <li><a class="op file-cp" href="#" data="{{ dirent.obj_name }}">复制</a></li>
<li><a class="op file-update" href="{{ SITE_ROOT }}repo/update_file/{{repo.id}}/?p={{ path }}{{dirent.obj_name}}">更新</a></li> <li><a class="op file-update" href="{{ SITE_ROOT }}repo/update_file/{{repo.id}}/?p={{ path|urlencode }}{{dirent.obj_name|urlencode}}">更新</a></li>
<li><a class="op list-revisions" href="{{ SITE_ROOT }}repo/file_revisions/{{repo.id}}/?p={{ path|urlencode}}{{dirent.obj_name|urlencode}}">历史</a></li>
{% endif %} {% endif %}
</ul> </ul>
</div> </div>

View File

@@ -23,6 +23,7 @@
<div class="side fright"> <div class="side fright">
<h3>操作</h3> <h3>操作</h3>
<p><a href="{{ SITE_ROOT }}repo/{{ repo.id }}/{{ obj_id }}/?file_name={{ file_name }}&op=view" target="_blank">查看原始文件</a></p> <p><a href="{{ SITE_ROOT }}repo/{{ repo.id }}/{{ obj_id }}/?file_name={{ file_name }}&op=view" target="_blank">查看原始文件</a></p>
<p><a href="{{ SITE_ROOT }}repo/file_revisions/{{ repo.id }}/?p={{ path|urlencode }}">查看所有历史版本</a></p>
<p><a href="{{ SITE_ROOT }}repo/{{ repo.id }}/{{ obj_id }}/?file_name={{ file_name }}&op=download" target="_blank">下载文件</a></p> <p><a href="{{ SITE_ROOT }}repo/{{ repo.id }}/{{ obj_id }}/?file_name={{ file_name }}&op=download" target="_blank">下载文件</a></p>
</div> </div>

View File

@@ -12,7 +12,7 @@ from seahub.views import root, peers, myhome, \
seafile_access_check, back_local, repo_history_changes, \ seafile_access_check, back_local, repo_history_changes, \
repo_upload_file, file_upload_progress, file_upload_progress_page, get_subdir, file_move, \ repo_upload_file, file_upload_progress, file_upload_progress_page, get_subdir, file_move, \
repo_new_dir, repo_rename_file, validate_filename, \ repo_new_dir, repo_rename_file, validate_filename, \
repo_create, repo_update_file repo_create, repo_update_file, file_revisions
from seahub.notifications.views import notification_list from seahub.notifications.views import notification_list
from seahub.share.views import share_admin from seahub.share.views import share_admin
from seahub.group.views import group_list from seahub.group.views import group_list
@@ -51,6 +51,7 @@ urlpatterns = patterns('',
(r'^repo/file_rename/$', repo_rename_file), (r'^repo/file_rename/$', repo_rename_file),
url(r'^repo/upload_file/(?P<repo_id>[^/]+)/$', repo_upload_file, name='repo_upload_file'), url(r'^repo/upload_file/(?P<repo_id>[^/]+)/$', repo_upload_file, name='repo_upload_file'),
url(r'^repo/update_file/(?P<repo_id>[^/]+)/$', repo_update_file, name='repo_update_file'), url(r'^repo/update_file/(?P<repo_id>[^/]+)/$', repo_update_file, name='repo_update_file'),
url(r'^repo/file_revisions/(?P<repo_id>[^/]+)/$', file_revisions, name='file_revisions'),
url(r'^repo/(?P<repo_id>[^/]+)/$', repo, name='repo'), url(r'^repo/(?P<repo_id>[^/]+)/$', repo, name='repo'),
(r'^repo/history/(?P<repo_id>[^/]+)/$', repo_history), (r'^repo/history/(?P<repo_id>[^/]+)/$', repo_history),
(r'^repo/history/revert/(?P<repo_id>[^/]+)/$', repo_history_revert), (r'^repo/history/revert/(?P<repo_id>[^/]+)/$', repo_history_revert),
@@ -59,7 +60,7 @@ urlpatterns = patterns('',
(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),
# (r'^repo/setap/(?P<repo_id>[^/]+)/$', repo_set_access_property), # (r'^repo/setap/(?P<repo_id>[^/]+)/$', repo_set_access_property),
(r'^repo/(?P<repo_id>[^/]+)/(?P<obj_id>[^/]+)/$', repo_access_file), url(r'^repo/(?P<repo_id>[^/]+)/(?P<obj_id>[^/]+)/$', repo_access_file, name='repo_access_file'),
(r'^repo/(?P<repo_id>[^/]+)/view/(?P<obj_id>[^/]+)/$', repo_view_file), (r'^repo/(?P<repo_id>[^/]+)/view/(?P<obj_id>[^/]+)/$', repo_view_file),
(r'^download/repo/$', repo_download), (r'^download/repo/$', repo_download),

View File

@@ -142,7 +142,7 @@ class UploadProgressCachedHandler(FileUploadHandler):
def check_filename_with_rename(repo_id, parent_dir, filename): def check_filename_with_rename(repo_id, parent_dir, filename):
latest_commit = get_commits(repo_id, 0, 1)[0] latest_commit = get_commits(repo_id, 0, 1)[0]
dirents = seafserv_rpc.list_dir_by_path(latest_commit.id, dirents = seafserv_threaded_rpc.list_dir_by_path(latest_commit.id,
parent_dir.encode('utf-8')) parent_dir.encode('utf-8'))
def no_duplicate(name): def no_duplicate(name):
@@ -183,7 +183,7 @@ def get_accessible_repos(request, repo):
if latest_commit.root_id == EMPTY_SHA1: if latest_commit.root_id == EMPTY_SHA1:
return False return False
dirs = seafserv_rpc.list_dir_by_path(latest_commit.id, '/') dirs = seafserv_threaded_rpc.list_dir_by_path(latest_commit.id, '/')
for dirent in dirs: for dirent in dirs:
if stat.S_ISDIR(dirent.props.mode): if stat.S_ISDIR(dirent.props.mode):
@@ -237,3 +237,20 @@ def valid_previewed_file(filename):
if fileExt in PREVIEW_FILEEXT.get(filetype): if fileExt in PREVIEW_FILEEXT.get(filetype):
return (True, filetype) return (True, filetype)
return (False, '') return (False, '')
def get_file_revision_id_size (commit_id, path):
"""Given a commit and a file path in that commit, return the seafile id
and size of the file blob
"""
dirname = os.path.dirname(path)
filename = os.path.basename(path)
seafdir = seafserv_threaded_rpc.list_dir_by_path (commit_id, dirname)
for dirent in seafdir:
if dirent.obj_name == filename:
file_size = seafserv_threaded_rpc.get_file_size(dirent.obj_id)
return dirent.obj_id, file_size
return None, None

130
views.py
View File

@@ -37,7 +37,8 @@ from forms import AddUserForm
from utils import go_permission_error, go_error, list_to_string, \ from utils import go_permission_error, go_error, list_to_string, \
get_httpserver_root, get_ccnetapplet_root, gen_token, \ get_httpserver_root, get_ccnetapplet_root, gen_token, \
calculate_repo_last_modify, valid_previewed_file, \ calculate_repo_last_modify, valid_previewed_file, \
check_filename_with_rename, get_accessible_repos, EMPTY_SHA1 check_filename_with_rename, get_accessible_repos, EMPTY_SHA1, \
get_file_revision_id_size
from seahub.profile.models import Profile from seahub.profile.models import Profile
from settings import FILE_PREVIEW_MAX_SIZE from settings import FILE_PREVIEW_MAX_SIZE
@@ -203,7 +204,7 @@ def render_repo(request, repo_id, error=''):
# view newest worktree or history worktree # view newest worktree or history worktree
commit_id = request.GET.get('commit_id', '') commit_id = request.GET.get('commit_id', '')
view_history = True if commit_id else False view_history = True if commit_id else False
current_commit = seafserv_rpc.get_commit(commit_id) current_commit = seafserv_threaded_rpc.get_commit(commit_id)
if not current_commit: if not current_commit:
current_commit = get_commits(repo_id, 0, 1)[0] current_commit = get_commits(repo_id, 0, 1)[0]
@@ -226,7 +227,7 @@ def render_repo(request, repo_id, error=''):
dirs = [] dirs = []
else: else:
try: try:
dirs = seafserv_rpc.list_dir_by_path(current_commit.id, dirs = seafserv_threaded_rpc.list_dir_by_path(current_commit.id,
path.encode('utf-8')) path.encode('utf-8'))
except SearpcError, e: except SearpcError, e:
return go_error(request, e.msg) return go_error(request, e.msg)
@@ -236,7 +237,7 @@ def render_repo(request, repo_id, error=''):
else: else:
file_list.append(dirent) file_list.append(dirent)
try: try:
dirent.file_size = seafserv_rpc.get_file_size(dirent.obj_id) dirent.file_size = seafserv_threaded_rpc.get_file_size(dirent.obj_id)
except: except:
dirent.file_size = 0 dirent.file_size = 0
dir_list.sort(lambda x, y : cmp(x.obj_name.lower(), dir_list.sort(lambda x, y : cmp(x.obj_name.lower(),
@@ -431,7 +432,7 @@ def get_subdir(request):
latest_commit = get_commits(repo_id, 0, 1)[0] latest_commit = get_commits(repo_id, 0, 1)[0]
try: try:
dirents = seafserv_rpc.list_dir_by_path(latest_commit.id, path.encode('utf-8')) dirents = seafserv_threaded_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)
@@ -443,7 +444,7 @@ def get_subdir(request):
dirent.has_subdir = False dirent.has_subdir = False
path_ = os.path.join (path, dirent.obj_name) path_ = os.path.join (path, dirent.obj_name)
try: try:
dirs_ = seafserv_rpc.list_dir_by_path(latest_commit.id, path_.encode('utf-8')) dirs_ = seafserv_threaded_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)
@@ -793,7 +794,7 @@ def repo_view_file(request, repo_id, obj_id):
filename = urllib2.quote(request.GET.get('file_name', '').encode('utf-8')) filename = urllib2.quote(request.GET.get('file_name', '').encode('utf-8'))
commit_id = request.GET.get('commit_id', '') commit_id = request.GET.get('commit_id', '')
view_history = True if commit_id else False view_history = True if commit_id else False
current_commit = seafserv_rpc.get_commit(commit_id) current_commit = seafserv_threaded_rpc.get_commit(commit_id)
if not current_commit: if not current_commit:
current_commit = get_commits(repo_id, 0, 1)[0] current_commit = get_commits(repo_id, 0, 1)[0]
@@ -864,7 +865,7 @@ def repo_view_file(request, repo_id, obj_id):
# query commit info # query commit info
commit_id = request.GET.get('commit_id', None) commit_id = request.GET.get('commit_id', None)
current_commit = seafserv_rpc.get_commit(commit_id) current_commit = seafserv_threaded_rpc.get_commit(commit_id)
if not current_commit: if not current_commit:
current_commit = get_commits(repo.id, 0, 1)[0] current_commit = get_commits(repo.id, 0, 1)[0]
@@ -885,6 +886,7 @@ def repo_view_file(request, repo_id, obj_id):
return render_to_response('repo_view_file.html', { return render_to_response('repo_view_file.html', {
'repo': repo, 'repo': repo,
'path': path,
'obj_id': obj_id, 'obj_id': obj_id,
'file_name': filename, 'file_name': filename,
'zipped': zipped, 'zipped': zipped,
@@ -1547,8 +1549,6 @@ def repo_rename_file(request):
newname = request.POST.get("newname") newname = request.POST.get("newname")
user = request.user.username user = request.user.username
# print repo_id, parent_dir, oldname, newname, user
if not newname: if not newname:
error_msg = u"新文件名不能为空" error_msg = u"新文件名不能为空"
return go_error(request, error_msg) return go_error(request, error_msg)
@@ -1646,3 +1646,113 @@ def repo_create(request):
error_msg = u"创建目录失败" error_msg = u"创建目录失败"
return render_repo_create_error(error_msg) return render_repo_create_error(error_msg)
return HttpResponseRedirect(reverse(myhome)) return HttpResponseRedirect(reverse(myhome))
def render_file_revisions (request, repo_id):
"""List all history versions of a file."""
target_file = request.GET.get('p')
if not target_file:
return go_error(request)
repo = get_repo(repo_id)
if not repo:
error_msg = u"同步目录不存在"
return go_error(request, error_msg)
try:
commits = seafserv_threaded_rpc.list_file_revisions(repo_id, target_file)
except SearpcError, e:
return go_error(request, e.msg)
if not commits:
return go_error(request)
# Check whether use is repo owner
if validate_owner(request, repo_id):
is_owner = True
else:
is_owner = False
try:
current_commit = get_commits(repo_id, 0, 1)[0]
current_file_id = get_file_revision_id_size (current_commit.id, target_file)[0]
for commit in commits:
file_id, file_size = get_file_revision_id_size (commit.id, target_file)
if not file_id or not file_size:
return go_error(request)
commit.revision_file_size = file_size
if file_id == current_file_id:
commit.is_current_version = True
else:
commit.is_current_version = False
except Exception, e:
return go_error(request, str(e))
return render_to_response('file_revisions.html', {
'repo': repo,
'path': target_file,
'commits': commits,
'is_owner': is_owner,
}, context_instance=RequestContext(request))
@login_required
def file_revisions(request, repo_id):
if request.method != 'GET':
return go_error(request)
op = request.GET.get('op')
if not op:
return render_file_revisions(request, repo_id)
elif op != 'revert' and op != 'download' and op != 'view':
return go_error(request)
commit_id = request.GET.get('commit')
path = request.GET.get('p')
if not (commit_id and path):
return go_error(request)
if op == 'revert':
try:
seafserv_threaded_rpc.revert_file (repo_id, commit_id,
path, request.user.username)
except Exception, e:
return go_error(request, str(e))
else:
parent_dir = os.path.dirname(path)
url = reverse('repo', args=[repo_id]) + ('?p=%s' % parent_dir)
return HttpResponseRedirect(url)
elif op == 'download':
def handle_download():
parent_dir = os.path.dirname(path)
file_name = os.path.basename(path)
seafdir = seafserv_threaded_rpc.list_dir_by_path (commit_id, \
parent_dir.encode('utf-8'))
if not seafdir:
return go_error(request)
# for ... else ...
for dirent in seafdir:
if dirent.obj_name == file_name:
break
else:
return go_error(request)
url = reverse('repo_access_file', args=[repo_id, dirent.obj_id])
url += '?file_name=%s&op=download' % file_name
return HttpResponseRedirect(url)
try:
return handle_download()
except Exception, e:
return go_error(request, str(e))
elif op == 'view':
seafile_id = get_file_revision_id_size (commit_id, path)[0]
if not seafile_id:
return go_error(request)
file_name = os.path.basename(path)
url = reverse(repo_view_file, args=[repo_id, seafile_id])
url += u'?commit_id=%s&file_name=%s&p=%s' \
% (commit_id, file_name, path)
return HttpResponseRedirect(url)