import os, sys from git import * import bottle from bottle import default_app, route, run, request, template, static_file, redirect from os.path import isdir from string import lower, split from urllib import unquote import shutil from datetime import datetime import re import Image from markdown2 import markdown conf = {} conf['repo'] = '/srv/git/documents' #conf['repo'] = '/srv/git/repo' conf['ext_bundles'] = ['.pages', '.sparsebundle'] conf['ext_render'] = ['.md','.txt', '.jpg'] conf['ext_edit'] = ['.md','.txt','.rb','.py','.pl','.sh'] def sanitize_path(path): return path.lstrip('./') @route('/repo') @route('/repo/') @route('/repo/') def public(name=''): repo = Repo(conf['repo']) repo.git.pull() tree = [] filename, extension = os.path.splitext(name) filename = os.path.basename(filename) path = os.path.join(conf['repo'], sanitize_path(name)) if os.path.exists(path): if isdir(path) and not lower(extension) in conf['ext_bundles']: tree.append('') tree.append('

Upload ') tree.append('New File ') tree.append('New Dir

') return template('templates/yield', content="\n".join(tree), title="Files in "+sanitize_path(name)) else: if isdir(path) and lower(extension) in conf['ext_bundles']: print "This is a bundle: " + sanitize_path(name) d = datetime.now() basedir = re.sub(filename+extension, '', path) rootdir = filename+extension z = shutil.make_archive('/tmp/' + unquote(filename) + '_' + \ d.strftime("%Y%M%d%H%M%S"), "zip", basedir, rootdir ) return static_file(os.path.basename(z), root='/tmp') if lower(extension) in conf['ext_render']: print "This is a render: " + sanitize_path(name) try: Image.open(path) content = '' except: try: o = open(path,'r') content = markdown(o.read()) o.close() content += '

Edit - \ Raw

' except: content = "

This cannot be rendered.

" return template('templates/yield', content = content, \ title=filename+extension) else: print "This is a file: " + unquote(name) return static_file(unquote(name), root=conf['repo']) else: return 'File does not exist.' @route('/raw/') def raw(path=False): try: return static_file(unquote(path),root=conf['repo']) except: return 'No such file' @route('/upload/:path', method="GET") @route('/upload/', method="GET") @route('/upload', method="GET") def upload(path=''): path = sanitize_path(path) body = [] body.append('') body.append('

Upload a new file

') body.append('
') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('
') body.append('
') return template('templates/yield', content='\n'.join(body), \ title='Add') @route('/upload', method="POST") def do_upload(): repo = Repo(conf['repo']) repo.git.pull() path = request.forms.path path = sanitize_path(path) message = request.forms.message u = request.files.uploaded filename = u.filename new_file = os.path.join(conf['repo'],path,filename) if not os.path.exists(os.path.join(conf['repo'],path)): os.mkdir(os.path.join(conf['repo'],path)) overwritten = False if os.path.exists(new_file): overwritten = True w = open(new_file,'wb') w.write(u.file.read()) w.close() content = ['

' + filename + ' uploaded to\ /' + path + ''] if overwritten: content.append(' (original overwritten).

') else: content.append('.

') if not overwritten or (overwritten and not repo.git.diff(new_file) == ""): repo.git.add(new_file) content.append("

Git: ") commit_result = repo.git.commit(new_file,m=message) repo.git.push() content.append(commit_result) content.append('

') else: content.append('

Git: file is not different.

') content.append('

Upload another.

') return template('templates/yield', content='\n'.join(content), title='"'+filename+'" uploaded.') @route('/delete', method="GET") @route('/delete/', method="GET") def delete(path = ''): body = [] path = sanitize_path(path) body.append('') body.append('

Delete a file

') body.append('
') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('
') body.append('
') return template('templates/yield', content='\n'.join(body), title='Delete') @route('/delete', method='POST') def delete(): body = [] repo = Repo(conf['repo']) path = request.forms.path path = sanitize_path(path) directory,filename = os.path.split(path) directory = '/'+directory message = request.forms.message result = False repo.git.pull() if os.path.exists(os.path.join(conf['repo'],path)): try: repo.git.rm(path, r=True) result = repo.git.commit(path, m=message) repo.git.push() except: if not isdir(os.path.join(conf['repo'],path)): os.remove(os.path.join(conf['repo'],path)) body.append('

' + path + ' deleted from '+directory+'.

') if result: body.append('

Git: '+result+'

') else: body.append('

'+path+' does not exist.

') return template('templates/yield', content='\n'.join(body), title=path+' deleted.') @route('/edit/', method='GET') @route('/edit', method="GET") def edit(path=''): if not path and request.query.path: path = request.query.path path = sanitize_path(path) body = [] if path: full = os.path.join(conf['repo'],path) False, ext = os.path.splitext(path) if os.path.exists(full) and not isdir(full) and ext in conf['ext_edit']: body.append('') body.append('

Editing '+ path +'

') body.append('
') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('
') body.append('
') else: body.append('

Path does not exist or is not editable.') else: body.append('

Edit a file

') body.append('
') body.append('') body.append('') body.append('') body.append('') body.append('
') body.append('
') return template('templates/yield', content='\n'.join(body), \ title='New') @route('/edit', method='POST') def edit(): repo = Repo(conf['repo']) path = request.forms.path content = request.forms.content message = request.forms.message full_path = os.path.join(conf['repo'],path) repo.git.pull() body = [] f = open(full_path, 'w') f.write(content) f.close() if not repo.git.diff(path) == '': commit = repo.git.commit(path,m=message) repo.git.push() body.append('

' + path + ' edited.

') body.append('

Git: ' + commit + '

') else: body.append('

' + path + ' not changed.

') return template('templates/yield', content='\n'.join(body),\ title=path+' edited.') @route('/new', method='GET') @route('/new/', method='GET') def new(path = ''): path = sanitize_path(path) body = [] body.append('') body.append('

Create a new file

') body.append('
') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('
') body.append('
') return template('templates/yield', content='\n'.join(body), \ title='New') @route('/new', method="POST") def new(): filename = request.forms.name directory = sanitize_path(request.forms.path) content = request.forms.content message = request.forms.message full_path = os.path.join(conf['repo'], directory, filename) w = open(full_path, 'w') w.write(content) w.close() repo = Repo(conf['repo']) repo.git.pull() commit = False overwritten = False if os.path.exists(os.path.join(directory,filename)): overwritten = True diff = repo.git.diff(os.path.join(directory,filename)) if not overwritten or (overwritten and not diff == ''): repo.git.add(os.path.join(directory, filename)) commit = repo.git.commit(os.path.join(directory, filename),m=message) repo.git.push() body = [] body.append('

'+filename+' added to '+(directory if not directory == '' else '/')+'

') if commit: body.append('

Git: '+commit+'

') return template('templates/yield', content='\n'.join(body), \ title=filename + ' created') @route('/move/', method="GET") @route('/move', method="GET") def rename(path = ''): body = [] path = sanitize_path(path) body.append('') body.append('

Move

') body.append('
') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('') body.append('
') body.append('
') return template('templates/yield', content='\n'.join(body),\ title='move') @route('/move', method="POST") def rename(): current = os.path.join(conf['repo'],sanitize_path(request.forms.current)) new = os.path.join(conf['repo'],sanitize_path(request.forms.destination)) message = request.forms.message body = [] if current and new: if os.path.exists(current): if not os.path.exists(new): repo = Repo(conf['repo']) repo.git.pull() repo.git.mv(current,new) if not message: message = datetime.now().isoformat() commit = repo.git.commit(current,new,m=message) repo.git.push() body.append('

'+request.forms.current+' moved to '\ +request.forms.destination+'.

') body.append('

Git: '+commit+'

') else: body.append('

'+request.forms.destination+' already exists.

') else: body.append('

'+request.forms.current+' does not exist.

') else: body.append('

Must have both a current and new name.

') return template('templates/yield', content='\n'.join(body),\ title=request.forms.current+' moved to '+request.forms.destination) @route('/mkdir/', method="GET") @route('/mkdir', method="GET") def mkdir(path=''): body = [] path = sanitize_path(path) body.append('') body.append('

Create Directory

') body.append('
') body.append('') body.append('') body.append('') body.append('') body.append('
') body.append('
') return template('templates/yield', content='\n'.join(body),\ title='Create Directory') @route('/mkdir', method="POST") def mkdir(): body = [] path = request.forms.path path = sanitize_path(path) if not os.path.exists(os.path.join(conf['repo'],path)): os.mkdir(os.path.join(conf['repo'],path)) if isdir(os.path.join(conf['repo'],path)): body.append('

' + path + ' created.

') else: body.append('

Directory could not be created

') else: body.append('

Path exists.

') return template('templates/yield', content='\n'.join(body),\ title='Create Directory') @route('/api') def api(): return 'Someday there will be an API here.' @route('/') def index(): redirect('/repo') application = bottle.default_app() if __name__ == "__main__": conf['repo'] = os.path.expanduser('~/dev/repo') run(host="127.0.0.1", port=8000, reloader=True)