Exemple #1
0
def live_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('live.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('live.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')
    allow_edits = set_meta_form.cleaned_data.get('anyone_can_edit')

    # 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,
            anyone_can_edit=allow_edits,
            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 = 'paste'

        # 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_abs_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
            filename += 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_abs_base, i, ext)
            filename = '%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='friendly',
                    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.commit = new_commit

    commit.save()

    if not paste_set.private:
        return redirect('paste_view', pk=paste_set.pk)
    else:
        return redirect('paste_view', pk=paste_set.pk, private_key=paste_set.private_key)

    return render_to_response('live.html')
Exemple #2
0
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() and
            set_form.is_valid() and
            commit_meta_form.is_valid() and
            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))

    owner       = get_owner(request, commit_meta_form.cleaned_data, request.user)
    description = set_form.cleaned_data.get('description')
    private     = set_meta_form.cleaned_data.get('private')
    allow_edits = set_meta_form.cleaned_data.get('anyone_can_edit')

    repo_dir = dirname_from_description(description)
    if os.path.isdir(repo_dir):
        repo_dir = get_first_nonexistent_filename(repo_dir + '-%d')

    os.mkdir(repo_dir)

    # 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.sample(string.ascii_letters + string.digits,
                                    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,
            anyone_can_edit=allow_edits,
            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'])
    with open(priority_filename, 'w') as priority_file:
        for form_index, form in enumerate(paste_forms):
            priority_file.write('%s: %s\n' % process_pasted_file(form_index,
                                                                 form,
                                                                 repo_dir,
                                                                 index, commit))

    index.add([priority_filename])

    # Create the commit from the index
    new_commit = index.commit('Initial paste.')
    commit.commit = new_commit
    commit.save()

    if paste_set.private:
        return redirect('paste_view', pk=paste_set.pk, private_key=paste_set.private_key)
    else:
        return redirect('paste_view', pk=paste_set.pk)
Exemple #3
0
def paste(request):
    commit_kwargs = {}
    user = request.user
    if user.is_authenticated():
        if settings.ALLOW_ANONYMOUS_POSTS:
            commit_kwargs = {'anonymous': user.preference.default_anonymous}
    elif not settings.ALLOW_ANONYMOUS_POSTS:
        return redirect('login')
    elif not settings.ALLOW_ANONYMOUS_ACCESS:
        return redirect('login')

    if request.method != 'POST':
        return render_to_response(
            'paste.html', {
                'allow_anonymous_posts': settings.ALLOW_ANONYMOUS_POSTS,
                '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() and set_form.is_valid()
            and commit_meta_form.is_valid() and set_meta_form.is_valid()):
        return render_to_response(
            'paste.html', {
                'allow_anonymous_posts': settings.ALLOW_ANONYMOUS_POSTS,
                'forms': paste_forms,
                'set_form': set_form,
                'commit_meta_form': commit_meta_form,
                'set_meta_form': set_meta_form,
            }, RequestContext(request))

    owner = get_owner(request, commit_meta_form.cleaned_data, request.user)
    description = set_form.cleaned_data.get('description')
    private = set_meta_form.cleaned_data.get('private')
    allow_edits = set_meta_form.cleaned_data.get('anyone_can_edit')

    repo_dir = dirname_from_description(description)
    if not len(description):
        repo_dir = dirname_from_description(''.join(
            random.sample(string.ascii_letters + string.digits,
                          random.randrange(20, 30))))
    if os.path.isdir(repo_dir):
        repo_dir = get_first_nonexistent_filename(repo_dir + '-%d')

    os.mkdir(repo_dir)

    # 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.sample(string.ascii_letters + string.digits,
                      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,
        anyone_can_edit=allow_edits,
        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'])
    with codecs.open(priority_filename, 'w', "utf-8-sig") as priority_file:
        for form_index, form in enumerate(paste_forms):
            priority_file.write(
                '%s: %s\n' %
                process_pasted_file(form_index, form, repo_dir, index, commit))

    index.add([priority_filename])

    # Create the commit from the index
    new_commit = index.commit('Initial paste.')
    commit.commit = new_commit
    commit.save()

    if paste_set.private:
        return redirect('paste_view',
                        pk=paste_set.pk,
                        private_key=paste_set.private_key)
    else:
        return redirect('paste_view', pk=paste_set.pk)
Exemple #4
0
def live_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(
            'live.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(
            'live.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')
    allow_edits = set_meta_form.cleaned_data.get('anyone_can_edit')

    # 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,
        anyone_can_edit=allow_edits,
        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 = 'paste'

        # 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_abs_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
            filename += 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_abs_base, i, ext)
            filename = '%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='friendly',
                          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.commit = new_commit

    commit.save()

    if not paste_set.private:
        return redirect('paste_view', pk=paste_set.pk)
    else:
        return redirect('paste_view',
                        pk=paste_set.pk,
                        private_key=paste_set.private_key)

    return render_to_response('live.html')
Exemple #5
0
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 or "never",
        'anyone_can_edit': paste_set.anyone_can_edit
    }

    #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))

    set_form = None
    set_meta_form = None
    forms = PasteSetEdit(request.POST, initial=initial_data)
    commit_meta_form = CommitMetaForm(request.POST)
    form_list = [forms, commit_meta_form]
    if request.user == paste_set.owner:
        set_form = SetForm(request.POST)
        set_meta_form = SetMetaForm(request.POST)
        form_list += [set_form, set_meta_form]

    if not all(map(lambda x: x.is_valid(), form_list)):
        return render_to_response(
            'paste.html', {
                'forms': forms,
                'set_form': set_form,
                'commit_meta_form': commit_meta_form,
                'set_meta_form': set_meta_form,
                '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:
        fdata = set_form.cleaned_data
        paste_set.description = fdata['description']

    if set_meta_form:
        fdata = set_meta_form.cleaned_data
        paste_set.private = fdata.get('private')
        paste_set.anyone_can_edit = fdata.get('anyone_can_edit')

    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'])
    with codecs.open(priority_filename, 'w', "utf-8-sig") as priority_file:
        for form_index, form in enumerate(forms):
            filename, priority = process_pasted_file(form_index, form,
                                                     repo_dir, index, commit,
                                                     True)
            form_files.append(filename)
            priority_file.write('%s: %s\n' % (filename, 'priority'))

    # 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])])
    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:
        return redirect('paste_view', pk=paste_set.pk)
    else:
        return redirect('paste_view',
                        pk=paste_set.pk,
                        private_key=paste_set.private_key)
Exemple #6
0
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)
Exemple #7
0
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)