brain/brain.py

581 lines
20 KiB
Python

import os, sys
from git import *
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/<name:path>')
def public(name=''):
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('<ul>')
print "This is a regular dir: " + path
if not name == '':
n = name.rstrip('/')
l = split(n, '/')
tree.append('<li>')
if len(l) > 1:
tree.append('<a href="/repo/'+'/'.join(l[0:-1])+'">..</a>')
else:
tree.append('<a href="/repo/">..</a>')
tree.append('</li>')
dirs = []
files = []
for f in sorted(os.listdir(path)):
if not f.startswith('.') and not f.startswith('_'):
if isdir(os.path.join(path,f)):
dirs.append('<li>')
dirs.append('<a href="/repo/'+os.path.join(sanitize_path(name),f)+'">'+f+'</a>')
dirs.append('<a href="/move/'+os.path.join(sanitize_path(name),f)+'">(move)</a>')
dirs.append('<a href="/delete/'+os.path.join(sanitize_path(name),f)+'">(delete)</a>')
dirs.append('</li>')
else:
files.append('<li>')
files.append('<a href="/repo/'+os.path.join(sanitize_path(name),f)+'">'+f+'</a>')
False,e = os.path.splitext(f)
if e in conf['ext_edit']:
files.append('<a href="/edit/'+os.path.join(sanitize_path(name),f)+'">(edit)</a>')
files.append('<a href="/move/'+os.path.join(sanitize_path(name),f)+'">(move)</a>')
files.append('<a href="/delete/'+os.path.join(sanitize_path(name),f)+'">(delete)</a>')
files.append('</li>')
for d in dirs: tree.append(d)
for f in files: tree.append(f)
tree.append('</ul>')
tree.append('<p><a href="/upload/'+sanitize_path(name)+'">Upload</a> ')
tree.append('<a href="/new/'+sanitize_path(name)+'">New File</a> ')
tree.append('<a href="/mkdir/'+sanitize_path(name)+'">New Dir</a></p>')
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 = '<img src="/raw/'+sanitize_path(name)+'"/>'
except:
try:
o = open(path,'r')
content = markdown(o.read())
o.close()
content += '<p><a href="/edit/'+sanitize_path(name)+'">Edit</a> - \
<a href="/raw/'+sanitize_path(name)+'">Raw</a></p>'
except:
content = "<p>This cannot be rendered.</p>"
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/<path:path>')
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('<style type="text/css">\
td.r { text-align: left; }\
td.c { text-align: center; }\
td.l { text-align: right; }\
</style>')
body.append('<h1>Upload a new file</h1>')
body.append('<form style="width:500px;" method="post" action="/upload" enctype="multipart/form-data">')
body.append('<table>')
body.append('<tr><td class="l"><label for="uploaded">Upload:</label></td>')
body.append('<td class="r"><input type="file" name="uploaded" /></td></tr>')
body.append('<tr><td class="l"><label for="path">Destination:</label></td>')
body.append('<td class="r"><input type="text" name="path" style="width:250px" ')
if not path == '':
body.append('value="'+path+'" ')
body.append('/></td></tr>')
body.append('<tr><td class="l"><label for="message">Commit Message</label></td>')
body.append('<td class="r"><textarea name="message" cols="50" rows="7"></textarea></td></tr>')
body.append('<tr><td class="c"><input type="submit" name="submit"></td></tr>')
body.append('</table>')
body.append('</form>')
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 = ['<p><a href="/repo/'+path+'/'+filename+'">' + filename + '</a> uploaded to\
<a href="/repo/'+path+'">/' + path + '</a>']
if overwritten:
content.append(' (original overwritten).</p>')
else:
content.append('.</p>')
if not overwritten or (overwritten and not repo.git.diff(new_file) == ""):
repo.git.add(new_file)
content.append("<p>Git: ")
commit_result = repo.git.commit(new_file,m=message)
repo.git.push()
content.append(commit_result)
content.append('</p>')
else:
content.append('<p>Git: file is not different.</p>')
content.append('<p><a href="/upload">Upload another.</a></p>')
return template('templates/yield', content='\n'.join(content), title='"'+filename+'" uploaded.')
@route('/delete', method="GET")
@route('/delete/<path:path>', method="GET")
def delete(path = ''):
body = []
path = sanitize_path(path)
body.append('<style type="text/css">\
td.r { text-align: left; }\
td.c { text-align: center; }\
td.l { text-align: right; }\
</style>')
body.append('<h1>Delete a file</h1>')
body.append('<form style="width:500px;" method="post" action="/delete" enctype="multipart/form-data">')
body.append('<table>')
body.append('<tr><td class="l"><label for="path">File to be deleted:</label></td>')
body.append('<td class="r"><input type="text" name="path" style="width:250px" ')
if path: body.append('value="'+path+'" ')
body.append('/></td></tr>')
body.append('<tr><td class="l"><label for="message">Commit Message</label></td>')
body.append('<td class="r"><textarea name="message" cols="50" rows="7"></textarea></td></tr>')
body.append('<tr><td><label for="delete">Do you really want to delete?</label></td>')
body.append('<td class="c"><input type="submit" name="delete" value="Yes."></td></tr>')
body.append('</table>')
body.append('</form>')
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=" '"+re.sub("'","\\'",message)+"'")
repo.git.push()
except:
if not isdir(os.path.join(conf['repo'],path)):
os.remove(os.path.join(conf['repo'],path))
body.append('<p>' + path + ' deleted from <a href="/repo'+directory+'">'+directory+'</a>.</p>')
if result: body.append('<p>Git: '+result+'</p>')
else:
body.append('<p>'+path+' does not exist.</p>')
return template('templates/yield', content='\n'.join(body), title=path+' deleted.')
@route('/edit/<path:path>', 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('<style type="text/css">\
td.r { text-align: left; vertical-align:top;}\
td.c { text-align: center; }\
td.l { text-align: right; vertical-align:top;}\
</style>')
body.append('<h1>Editing '+ path +'</h1>')
body.append('<form style="width:500px;" method="post" action="/edit" enctype="multipart/form-data">')
body.append('<input type="hidden" name="path" value="'+path+'" />')
body.append('<table>')
body.append('<tr><td class="l"><label for="content">Content:</label></td>')
body.append('<td class="c" style="width:100%"><textarea name="content" cols="80" rows="80">')
with open(full,'r') as f: body.append(f.read())
body.append('</textarea></td></tr>')
body.append('<tr><td class="l"><label for="message">Commit Message</label></td>')
body.append('<td class="r"><textarea name="message" cols="50" rows="7"></textarea></td></tr>')
body.append('<tr><td class="c"><input type="submit" name="submit"></td></tr>')
body.append('</table>')
body.append('</form>')
else:
body.append('<p>Path does not exist or is not editable.')
else:
body.append('<h1>Edit a file</h1>')
body.append('<form style="width:500px;" method="get" action="/edit">')
body.append('<table>')
body.append('<tr><td><label for="path">File:</label></td>')
body.append('<td><input type="text" name="path" style="width:250px;" /></td></tr>')
body.append('<tr><td><input type="submit" /></td></tr>')
body.append('</table>')
body.append('</form>')
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('<p><a href="/repo/'+path+'">' + path + '</a> edited.</p>')
body.append('<p>Git: ' + commit + '</p>')
else:
body.append('<p>' + path + ' not changed.</p>')
return template('templates/yield', content='\n'.join(body),\
title=path+' edited.')
@route('/new', method='GET')
@route('/new/<path:path>', method='GET')
def new(path = ''):
path = sanitize_path(path)
body = []
body.append('<style type="text/css">\
td.r { text-align: left; vertical-align:top;}\
td.c { text-align: center; }\
td.l { text-align: right; vertical-align:top;}\
</style>')
body.append('<h1>Create a new file</h1>')
body.append('<form style="width:500px;" method="post" action="/new" enctype="multipart/form-data">')
body.append('<table>')
body.append('<tr><td class="l"><label for="name">Filename:</label></td>')
body.append('<td class="r"><input type="text" name="name" style="width:250px"/></td></tr>')
body.append('<tr><td class="l"><label for="path">Destination:</label></td>')
body.append('<td class="r"><input type="text" name="path" style="width:250px"')
if path: body.append('value="'+path+'" ')
body.append('/></td></tr>')
body.append('<tr><td class="l"><label for="content">Content:</label></td>')
body.append('<td class="c" style="width:100%"><textarea name="content" cols="80" rows="80"></textarea></td></tr>')
body.append('<tr><td class="l"><label for="message">Commit Message</label></td>')
body.append('<td class="r"><textarea name="message" cols="50" rows="7"></textarea></td></tr>')
body.append('<tr><td class="c"><input type="submit" name="submit"></td></tr>')
body.append('</table>')
body.append('</form>')
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)
repo.git.pull()
w = open(full_path, 'w')
w.write(content)
w.close()
repo = Repo(conf['repo'])
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('<p>'+filename+' added to <a href="/repo/'+directory+'">'+(directory if not directory == '' else '/')+'</a></p>')
if commit:
body.append('<p>Git: '+commit+'</p>')
return template('templates/yield', content='\n'.join(body), \
title=filename + ' created')
@route('/move/<path:path>', method="GET")
@route('/move', method="GET")
def rename(path = ''):
body = []
path = sanitize_path(path)
body.append('<style type="text/css">\
td.r { text-align: left; vertical-align:top;}\
td.c { text-align: center; }\
td.l { text-align: right; vertical-align:top;}\
</style>')
body.append('<h1>Move</h1>')
body.append('<form style="width:500px;" method="post" action="/move" enctype="multipart/form-data">')
body.append('<table>')
body.append('<tr><td class="l"><label for="name">Current:</label></td>')
body.append('<td class="r"><input type="text" name="current" style="width:250px"')
if path: body.append(' value="'+path+'" ')
body.append('/></td></tr>')
body.append('<tr><td class="l"><label for="path">Destination:</label></td>')
body.append('<td class="r"><input type="text" name="destination" style="width:250px"/></td></tr>')
body.append('<tr><td class="l"><label for="message">Commit Message</label></td>')
body.append('<td class="r"><textarea name="message" cols="50" rows="7"></textarea></td></tr>')
body.append('<tr><td class="c"><input type="submit" name="submit"></td></tr>')
body.append('</table>')
body.append('</form>')
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('<p>'+request.forms.current+' moved to '\
+request.forms.destination+'.</p>')
body.append('<p>Git: '+commit+'</p>')
else:
body.append('<p>'+request.forms.destination+' already exists.</p>')
else:
body.append('<p>'+request.forms.current+' does not exist.</p>')
else:
body.append('<p>Must have both a current and new name.</p>')
return template('templates/yield', content='\n'.join(body),\
title=request.forms.current+' moved to '+request.forms.destination)
@route('/mkdir/<path:path>', method="GET")
@route('/mkdir', method="GET")
def mkdir(path=''):
body = []
path = sanitize_path(path)
body.append('<style type="text/css">\
td.r { text-align: left; vertical-align:top;}\
td.c { text-align: center; }\
td.l { text-align: right; vertical-align:top;}\
</style>')
body.append('<h1>Create Directory</h1>')
body.append('<form style="width:500px;" method="post" action="/mkdir" enctype="multipart/form-data">')
body.append('<table>')
body.append('<tr><td class="l"><label for="name">Name:</label></td>')
body.append('<td class="r"><input type="text" name="path" style="width:250px"')
if path: body.append(' value="'+path+'" ')
body.append('/></td></tr>')
body.append('<tr><td class="c"><input type="submit" name="submit"></td></tr>')
body.append('</table>')
body.append('</form>')
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('<p><a href="/repo/'+path+'">' + path + '</a> created.</p>')
else:
body.append('<p>Directory could not be created</p>')
else:
body.append('<p>Path exists.</p>')
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')
if __name__ == "__main__":
#run(host="127.0.0.1", port=9911, reloader=True)
application = default_app()