def paste(request): commit_kwargs = {} if request.user.is_authenticated(): commit_kwargs = { 'anonymous': request.user.preference.default_anonymous } if request.method != 'POST': return render_to_response( 'paste.html', { 'forms': PasteSet(), 'set_form': SetForm(), 'commit_meta_form': CommitMetaForm(initial=commit_kwargs), 'set_meta_form': SetMetaForm(), }, RequestContext(request)) paste_forms = PasteSet(request.POST) set_form = SetForm(request.POST) commit_meta_form = CommitMetaForm(request.POST, initial=commit_kwargs) set_meta_form = SetMetaForm(request.POST) if (not paste_forms.is_valid() or not set_form.is_valid() or not commit_meta_form.is_valid() or not set_meta_form.is_valid()): return render_to_response( 'paste.html', { 'forms': paste_forms, 'set_form': set_form, 'commit_meta_form': commit_meta_form, 'set_meta_form': set_meta_form, }, RequestContext(request)) # Repositories are just a random sequence of letters and digits # We store the reference repository for editing the pastes. repo_dir = os.sep.join([ settings.REPO_DIR, "".join(random.sample(string.letters + string.digits, 15)) ]) anonymous = commit_meta_form.cleaned_data.get('anonymous') os.mkdir(repo_dir) owner = None if request.user.is_authenticated() and not anonymous: owner = request.user description = set_form.cleaned_data.get('description') private = set_meta_form.cleaned_data.get('private') # Calculate expiration time of set if necessary exp_option = set_meta_form.cleaned_data.get('expires') exp_map = { 'day': timedelta(days=1), 'hour': timedelta(hours=1), 'month': timedelta(365 / 12), } exp_time = datetime.utcnow( ) + exp_map[exp_option] if exp_option in exp_map else None # Generate a random hash for private access (20-30 characters from letters & numbers) private_key = ''.join( random.choice(string.ascii_letters + string.digits) for x in range(random.randrange(20, 30))) # Create a new paste set so we can reference our paste. paste_set = Set.objects.create( views=0, repo=repo_dir, owner=owner, description=description, private=private, private_key=private_key, expires=exp_time, ) # Yes, this is horrible. I know. But there is a bug with Python Git. # See: https://github.com/gitpython-developers/GitPython/issues/39 os.environ['USER'] = "******" if owner: os.environ['USER'] = owner.username # Initialize a commit, git repository, and pull the current index. commit = Commit.objects.create(views=0, parent_set=paste_set, commit='', owner=owner) git_repo = git.Repo.init(repo_dir) index = git_repo.index # We enumerate over the forms so we can have a way to reference # the line numbers in a unique way relevant to the pastes. priority_filename = os.sep.join([repo_dir, 'priority.txt']) priority_file = open(priority_filename, 'w') for form_index, form in enumerate(paste_forms): data = form.cleaned_data filename = data['filename'] language_lex, language = data['language'].split(';') paste = data['paste'] # If we don't specify a filename, then obviously it is lonely if not len(filename): filename = 'a-lonely-file' # Construct a more logical filename for our commit filename_base, ext = os.path.splitext(filename) filename_slugify = slugify(filename[:len(ext)]) filename_absolute = os.sep.join([repo_dir, filename]) filename_absolute += ext filename_base, ext = os.path.splitext(filename_absolute) # If no extension was specified in the file, then we can append # the extension from the lexer. if not len(ext): filename_absolute += language ext = language # Gists doesn't allow for the same filename, we do. # Just append a number to the filename and call it good. i = 1 while os.path.exists(filename_absolute): filename_absolute = '%s-%d%s' % (filename_base, i, ext) i += 1 cleaned = [] paste = paste.encode('UTF-8') for line in paste.split('\n'): line = line.rstrip() cleaned.append(line) paste = '\n'.join(cleaned) # Open the file, write the paste, call it good. f = open(filename_absolute, "w") f.write(paste) f.close() priority_file.write('%s: %s\n' % (filename, data['priority'])) paste = smart_unicode(paste) # This is a bit nasty and a get_by_ext something exist in pygments. # However, globals() is just much more fun. lex = globals()[language_lex] paste_formatted = highlight( paste, lex(), HtmlFormatter(style='colorful', linenos='table', lineanchors='line-%s' % form_index, anchorlinenos=True)) # Add the file to the index and create the paste index.add([filename_absolute]) p = Paste.objects.create(filename=filename, absolute_path=filename_absolute, paste=paste, priority=data['priority'], paste_formatted=paste_formatted, language=data['language'], revision=commit) # Add a priority file priority_file.close() index.add([priority_filename]) # Create the commit from the index new_commit = index.commit('Initial paste.') commit.diff = _git_diff(new_commit, git_repo) commit.commit = new_commit commit.save() if not paste_set.private or user_owns_paste(paste_set, request.user): return redirect('paste_view', pk=paste_set.pk) else: return redirect('paste_view', pk=paste_set.pk, private_key=paste_set.private_key)
def paste(request): commit_kwargs = {} if request.user.is_authenticated(): commit_kwargs = { 'anonymous': request.user.preference.default_anonymous } if request.method != 'POST': return render_to_response('paste.html', { 'forms': PasteSet(), 'set_form': SetForm(), 'commit_meta_form': CommitMetaForm(initial=commit_kwargs), 'set_meta_form': SetMetaForm(), }, RequestContext(request)) paste_forms = PasteSet(request.POST) set_form = SetForm(request.POST) commit_meta_form = CommitMetaForm(request.POST, initial=commit_kwargs) set_meta_form = SetMetaForm(request.POST) if (not paste_forms.is_valid() or not set_form.is_valid() or not commit_meta_form.is_valid() or not set_meta_form.is_valid()): return render_to_response('paste.html', { 'forms': paste_forms, 'set_form': set_form, 'commit_meta_form': commit_meta_form, 'set_meta_form': set_meta_form, }, RequestContext(request)) # Repositories are just a random sequence of letters and digits # We store the reference repository for editing the pastes. repo_dir = os.sep.join([ settings.REPO_DIR, "".join(random.sample(string.letters + string.digits, 15)) ]) anonymous = commit_meta_form.cleaned_data.get('anonymous') os.mkdir(repo_dir) owner = None if request.user.is_authenticated() and not anonymous: owner = request.user description = set_form.cleaned_data.get('description') private = set_meta_form.cleaned_data.get('private') # Calculate expiration time of set if necessary exp_option = set_meta_form.cleaned_data.get('expires') exp_map = { 'day' : timedelta(days=1), 'hour' : timedelta(hours=1), 'month' : timedelta(365/12), } exp_time = datetime.utcnow() + exp_map[exp_option] if exp_option in exp_map else None # Generate a random hash for private access (20-30 characters from letters & numbers) private_key = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(random.randrange(20,30))) # Create a new paste set so we can reference our paste. paste_set = Set.objects.create( views=0, repo=repo_dir, owner=owner, description=description, private=private, private_key=private_key, expires=exp_time, ) # Yes, this is horrible. I know. But there is a bug with Python Git. # See: https://github.com/gitpython-developers/GitPython/issues/39 os.environ['USER'] = "******" if owner: os.environ['USER'] = owner.username # Initialize a commit, git repository, and pull the current index. commit = Commit.objects.create( views=0, parent_set=paste_set, commit='', owner=owner ) git_repo = git.Repo.init(repo_dir) index = git_repo.index # We enumerate over the forms so we can have a way to reference # the line numbers in a unique way relevant to the pastes. priority_filename = os.sep.join([repo_dir, 'priority.txt']) priority_file = open(priority_filename, 'w') for form_index, form in enumerate(paste_forms): data = form.cleaned_data filename = data['filename'] language_lex, language = data['language'].split(';') paste = data['paste'] # If we don't specify a filename, then obviously it is lonely if not len(filename): filename = 'a-lonely-file' # Construct a more logical filename for our commit filename_base, ext = os.path.splitext(filename) filename_slugify = slugify(filename[:len(ext)]) filename_absolute = os.sep.join([ repo_dir, filename ]) filename_absolute += ext filename_base, ext = os.path.splitext(filename_absolute) # If no extension was specified in the file, then we can append # the extension from the lexer. if not len(ext): filename_absolute += language ext = language # Gists doesn't allow for the same filename, we do. # Just append a number to the filename and call it good. i = 1 while os.path.exists(filename_absolute): filename_absolute = '%s-%d%s' % (filename_base, i, ext) i += 1 cleaned = [] paste = paste.encode('UTF-8') for line in paste.split('\n'): line = line.rstrip() cleaned.append(line) paste = '\n'.join(cleaned) # Open the file, write the paste, call it good. f = open(filename_absolute, "w") f.write(paste) f.close() priority_file.write('%s: %s\n' % (filename, data['priority'])) paste = smart_unicode(paste) # This is a bit nasty and a get_by_ext something exist in pygments. # However, globals() is just much more fun. lex = globals()[language_lex] paste_formatted = highlight( paste, lex(), HtmlFormatter( style='colorful', linenos='table', lineanchors='line-%s' % form_index, anchorlinenos=True) ) # Add the file to the index and create the paste index.add([filename_absolute]) p = Paste.objects.create( filename=filename, absolute_path=filename_absolute, paste=paste, priority=data['priority'], paste_formatted=paste_formatted, language=data['language'], revision=commit ) # Add a priority file priority_file.close() index.add([priority_filename]) # Create the commit from the index new_commit = index.commit('Initial paste.') commit.diff = _git_diff(new_commit, git_repo) commit.commit = new_commit commit.save() if not paste_set.private or user_owns_paste(paste_set, request.user): return redirect('paste_view', pk=paste_set.pk) else: return redirect('paste_view', pk=paste_set.pk, private_key=paste_set.private_key)
def paste_edit(request, pk, paste_set, private_key=None): requested_commit = request.GET.get('commit') # You can technically modify anything in history and update it if requested_commit is None: commit = paste_set.commit_set.latest('id') else: commit = get_object_or_404(Commit, parent_set=paste_set, commit=requested_commit) previous_files = [] for f in commit.paste_set.all(): previous_files.append(os.path.basename(f.absolute_path)) # Populate our initial data initial_data = [] for paste in commit.paste_set.all(): initial_data.append({ 'filename': paste.filename, 'paste': paste.paste, 'language': paste.language, }) initial_set_meta = { 'private': paste_set.private, 'expires': paste_set.expires, } #TODO: turn this into a template tag and allow template to do conversion original_expires_time = paste_set.expires expires_time = None if original_expires_time: if timezone.is_naive(original_expires_time): original_expires_time = original_expires_time.replace( tzinfo=timezone.utc) expires_time = original_expires_time.astimezone( timezone.get_current_timezone()) if request.method != 'POST': set_form = None if request.user == paste_set.owner: set_form_initial = {'description': paste_set.description} set_form = SetForm(initial=set_form_initial) return render_to_response( 'paste.html', { 'forms': PasteSetEdit(initial=initial_data), 'set_form': set_form, 'commit_meta_form': CommitMetaForm(), 'set_meta_form': SetMetaForm(initial=initial_set_meta), 'expires_time': expires_time, 'editing': True, }, RequestContext(request)) forms = PasteSetEdit(request.POST, initial=initial_data) commit_meta_form = CommitMetaForm(request.POST) set_form = None set_meta_form = None if request.user == paste_set.owner: set_form = SetForm(request.POST) set_meta_initial = { 'expires': 'never' } # to stop validation error, not used. is there a better way to do this? set_meta_form = SetMetaForm(request.POST, initial=set_meta_initial) if not forms.is_valid() or not commit_meta_form.is_valid() or ( set_form is not None and not set_form.is_valid()) or (set_meta_form is not None and not set_meta_form.is_valid()): return render_to_response( 'paste.html', { 'forms': forms, 'set_form': set_form, 'commit_meta_form': CommitMetaForm(), 'set_meta_form': SetMetaForm(initial=initial_set_meta), 'expires_time': expires_time, 'editing': True, }, RequestContext(request)) # Update the repo repo_dir = paste_set.repo repo = git.Repo(repo_dir) index = repo.index anonymous = commit_meta_form.cleaned_data['anonymous'] owner = None if request.user.is_authenticated() and not anonymous: owner = request.user # Yes, this is horrible. I know. But there is a bug with Python Git. # See: https://github.com/gitpython-developers/GitPython/issues/39 os.environ['USER'] = "******" if owner: os.environ['USER'] = owner.username if set_form: paste_set.description = set_form.cleaned_data['description'] paste_set.private = set_meta_form.cleaned_data.get('private') paste_set.save() commit = Commit.objects.create(views=0, parent_set=paste_set, commit='', owner=owner) # We enumerate over the forms so we can have a way to reference # the line numbers in a unique way relevant to the pastes. form_files = [] priority_filename = os.sep.join([repo_dir, 'priority.txt']) priority_file = open(priority_filename, 'w') for form_index, form in enumerate(forms): data = form.cleaned_data filename = data['filename'] language_lex, language = data['language'].split(';') paste = data['paste'] # If we don't specify a filename, then obviously it is lonely no_filename = False if not len(filename): no_filename = True filename = 'a-lonely-file' # Construct a more logical filename for our commit filename_base, ext = os.path.splitext(filename) filename_slugify = slugify(filename[:len(ext)]) filename_absolute = os.sep.join([repo_dir, filename]) filename_absolute += ext filename_base, ext = os.path.splitext(filename_absolute) # If no extension was specified in the file, then we can append # the extension from the lexer. if not len(ext): filename_absolute += language ext = language # Gists doesn't allow for the same filename, we do. # Just append a number to the filename and call it good. i = 1 if no_filename: while os.path.exists(filename_absolute): filename_absolute = '%s-%d%s' % (filename_base, i, ext) i += 1 form_files.append(os.path.basename(filename_absolute)) cleaned = [] paste = paste.encode('UTF-8') for line in paste.split('\n'): line = line.rstrip() cleaned.append(line) paste = '\n'.join(cleaned) # Open the file, write the paste, call it good. f = open(filename_absolute, "w") f.write(paste) f.close() priority_file.write('%s: %s\n' % (filename, data['priority'])) # This is a bit nasty and a get_by_ext something exist in pygments. # However, globals() is just much more fun. paste = smart_unicode(paste) lex = globals()[language_lex] paste_formatted = highlight( paste, lex(), HtmlFormatter(style='colorful', linenos='table', lineanchors='line-%s' % form_index, anchorlinenos=True)) # Add the file to the index and create the paste index.add([filename_absolute]) p = Paste.objects.create(filename=filename, absolute_path=filename_absolute, paste=paste, priority=data['priority'], paste_formatted=paste_formatted, language=data['language'], revision=commit) # Create the commit from the index intersected = set(form_files).intersection(previous_files) removed_files = list(set(previous_files) - intersected) for f in removed_files: index.remove([os.sep.join([repo_dir, f])]) priority_file.close() index.add([priority_filename]) new_commit = index.commit('Modified.') commit.commit = new_commit commit.diff = _git_diff(new_commit, repo) commit.save() if not paste_set.private or user_owns_paste(paste_set, request.user): return redirect('paste_view', pk=paste_set.pk) else: return redirect('paste_view', pk=paste_set.pk, private_key=paste_set.private_key)
def paste_edit(request, pk, paste_set, private_key=None): requested_commit = request.GET.get('commit') # You can technically modify anything in history and update it if requested_commit is None: commit = paste_set.commit_set.latest('id') else: commit = get_object_or_404(Commit, parent_set=paste_set, commit=requested_commit) previous_files = [] for f in commit.paste_set.all(): previous_files.append(os.path.basename(f.absolute_path)) # Populate our initial data initial_data = [] for paste in commit.paste_set.all(): initial_data.append({ 'filename': paste.filename, 'paste': paste.paste, 'language': paste.language, }) initial_set_meta = { 'private': paste_set.private, 'expires': paste_set.expires, } #TODO: turn this into a template tag and allow template to do conversion original_expires_time = paste_set.expires expires_time = None if original_expires_time: if timezone.is_naive(original_expires_time): original_expires_time = original_expires_time.replace(tzinfo=timezone.utc) expires_time = original_expires_time.astimezone(timezone.get_current_timezone()) if request.method != 'POST': set_form = None if request.user == paste_set.owner: set_form_initial = {'description': paste_set.description} set_form = SetForm(initial=set_form_initial) return render_to_response('paste.html', { 'forms': PasteSetEdit(initial=initial_data), 'set_form': set_form, 'commit_meta_form': CommitMetaForm(), 'set_meta_form': SetMetaForm(initial=initial_set_meta), 'expires_time': expires_time, 'editing': True, }, RequestContext(request)) forms = PasteSetEdit(request.POST, initial=initial_data) commit_meta_form = CommitMetaForm(request.POST) set_form = None set_meta_form = None if request.user == paste_set.owner: set_form = SetForm(request.POST) set_meta_initial = {'expires': 'never'} # to stop validation error, not used. is there a better way to do this? set_meta_form = SetMetaForm(request.POST, initial=set_meta_initial) if not forms.is_valid() or not commit_meta_form.is_valid() or ( set_form is not None and not set_form.is_valid() ) or ( set_meta_form is not None and not set_meta_form.is_valid()): return render_to_response('paste.html', { 'forms': forms, 'set_form': set_form, 'commit_meta_form': CommitMetaForm(), 'set_meta_form': SetMetaForm(initial=initial_set_meta), 'expires_time': expires_time, 'editing': True, }, RequestContext(request)) # Update the repo repo_dir = paste_set.repo repo = git.Repo(repo_dir) index = repo.index anonymous = commit_meta_form.cleaned_data['anonymous'] owner = None if request.user.is_authenticated() and not anonymous: owner = request.user # Yes, this is horrible. I know. But there is a bug with Python Git. # See: https://github.com/gitpython-developers/GitPython/issues/39 os.environ['USER'] = "******" if owner: os.environ['USER'] = owner.username if set_form: paste_set.description = set_form.cleaned_data['description'] paste_set.private = set_meta_form.cleaned_data.get('private') paste_set.save() commit = Commit.objects.create( views=0, parent_set=paste_set, commit='', owner=owner ) # We enumerate over the forms so we can have a way to reference # the line numbers in a unique way relevant to the pastes. form_files = [] priority_filename = os.sep.join([repo_dir, 'priority.txt']) priority_file = open(priority_filename, 'w') for form_index, form in enumerate(forms): data = form.cleaned_data filename = data['filename'] language_lex, language = data['language'].split(';') paste = data['paste'] # If we don't specify a filename, then obviously it is lonely no_filename = False if not len(filename): no_filename = True filename = 'a-lonely-file' # Construct a more logical filename for our commit filename_base, ext = os.path.splitext(filename) filename_slugify = slugify(filename[:len(ext)]) filename_absolute = os.sep.join([ repo_dir, filename ]) filename_absolute += ext filename_base, ext = os.path.splitext(filename_absolute) # If no extension was specified in the file, then we can append # the extension from the lexer. if not len(ext): filename_absolute += language ext = language # Gists doesn't allow for the same filename, we do. # Just append a number to the filename and call it good. i = 1 if no_filename: while os.path.exists(filename_absolute): filename_absolute = '%s-%d%s' % (filename_base, i, ext) i += 1 form_files.append(os.path.basename(filename_absolute)) cleaned = [] paste = paste.encode('UTF-8') for line in paste.split('\n'): line = line.rstrip() cleaned.append(line) paste = '\n'.join(cleaned) # Open the file, write the paste, call it good. f = open(filename_absolute, "w") f.write(paste) f.close() priority_file.write('%s: %s\n' % (filename, data['priority'])) # This is a bit nasty and a get_by_ext something exist in pygments. # However, globals() is just much more fun. paste = smart_unicode(paste) lex = globals()[language_lex] paste_formatted = highlight( paste, lex(), HtmlFormatter( style='colorful', linenos='table', lineanchors='line-%s' % form_index, anchorlinenos=True) ) # Add the file to the index and create the paste index.add([filename_absolute]) p = Paste.objects.create( filename=filename, absolute_path=filename_absolute, paste=paste, priority=data['priority'], paste_formatted=paste_formatted, language=data['language'], revision=commit ) # Create the commit from the index intersected = set(form_files).intersection(previous_files) removed_files = list(set(previous_files) - intersected) for f in removed_files: index.remove([os.sep.join([ repo_dir, f ])]) priority_file.close() index.add([priority_filename]) new_commit = index.commit('Modified.') commit.commit = new_commit commit.diff = _git_diff(new_commit, repo) commit.save() if not paste_set.private or user_owns_paste(paste_set, request.user): return redirect('paste_view', pk=paste_set.pk) else: return redirect('paste_view', pk=paste_set.pk, private_key=paste_set.private_key)