Beispiel #1
0
def download_submission(request, submission, revision):

    create_hit(request, submission, extra_info="download")
    if submission.sub_type == 'snippet':
        response = HttpResponse(mimetype="application/x-python")
        fname = submission.slug.replace('-', '_') + '.py'
        response["Content-Disposition"] = "attachment; filename=%s" % fname
        source = Site.objects.get_current().domain + \
                                                 submission.get_absolute_url()
        response.write('# Source: ' + source + '\n\n' + revision.item_code)
        return response

    if submission.sub_type == 'package':
        zip_dir = os.path.join(settings.SPC['ZIP_staging'], 'download')
        ensuredir(zip_dir)
        response = HttpResponse(mimetype="attachment; application/zip")
        zip_name = '%s-%d-%d.zip' % (submission.slug, submission.id,
                                     revision.rev_id_human)
        response['Content-Disposition'] = 'filename=%s' % zip_name
        full_zip_file = os.path.join(zip_dir, zip_name)
        if not os.path.exists(full_zip_file):

            # Set the repo's state to the state when that particular revision
            # existed
            out = submission.fileset.checkout_revision(revision.hash_id)
            if out:
                logger.info('Checked out revision "%s" for rev.id=%d' % \
                            (revision.hash_id, revision.id))
            else:
                logger.error('Could not checked out revision "%s" for '
                             'rev.id=%d' % (revision.hash_id, revision.id))
                return page_404_error(request, ('Could not create the ZIP '
                                                'file. This error has been '
                                                'reported.'))

            zip_f = zipfile.ZipFile(full_zip_file, "w", zipfile.ZIP_DEFLATED)
            src_dir = os.path.join(settings.SPC['storage_dir'],
                                   submission.fileset.repo_path)
            for path, dirs, files in os.walk(src_dir):
                for name in files:
                    file_name = os.path.join(path, name)
                    file_h = open(file_name, "r")
                    zip_f.write(file_name, file_name.partition(src_dir)[2])
                    file_h.close()

            for file_h in zip_f.filelist:
                file_h.create_system = 0

            zip_f.close()

            # Return the repo checkout back to the most recent revision
            out = submission.fileset.checkout_revision(submission.\
                                                       last_revision.hash_id)

        # Return the ZIP file
        zip_data = open(full_zip_file, "rb")
        response.write(zip_data.read())
        zip_data.close()
        return response
Beispiel #2
0
def profile_page(request, slug=None, user_id=None):
    """
    Shows the user's profile.
    """
    try:
        if user_id:
            the_user = models.User.objects.get(id=user_id)
            if the_user.is_active:
                return redirect(profile_page, the_user.profile.slug)
        elif slug is None:
            the_user = request.user
        else:
            the_user = models.User.objects.get(profile__slug=slug)
    except ObjectDoesNotExist:
        return page_404_error(request, 'No profile for that user.')

    # Don't show the profile for inactive (unvalidated) users
    if not (the_user.is_active):
        return page_404_error(request, "That user's profile isn't available.")

    # Items created by this user. Use the ``all()`` function first, to prevent
    # unvalidated submissions from showing
    all_revs = Revision.objects.all().filter(created_by=the_user)\
                                                    .order_by('-date_created')

    if the_user == request.user:
        no_entries = 'You have not submitted any entries to SciPy Central.'
    else:
        no_entries = 'This user has not submitted any entries to SciPy Central.'

    permalink = settings.SPC['short_URL_root'] + 'user/' + str(
        the_user.id) + '/'

    create_hit(request, the_user)
    return render_to_response(
        'person/profile.html', {},
        context_instance=RequestContext(
            request, {
                'theuser': the_user,
                'permalink': permalink,
                'entries': paginated_queryset(request, all_revs),
                'no_entries_message': no_entries,
            }))
Beispiel #3
0
def validate_submission(request, code):
    """
    Validate a submission (via an emailed link to the user).

    From BSD licensed code, James Bennett
    https://bitbucket.org/ubernostrum/django-registration/src/58eef8330b0f/registration/models.py
    """
    SHA1_RE = re.compile('^[a-f0-9]{40}$')
    if SHA1_RE.search(code):
        try:
            rev = models.Revision.objects.get(validation_hash=code)
        except ObjectDoesNotExist:
            return page_404_error(request, ('That validation code was invalid'
                                            ' or used already.'))

        rev.is_displayed = True
        rev.validation_hash = None
        rev.save()
        return redirect(rev.get_absolute_url())
    else:
        return page_404_error(request, ('That validation code is invalid.'))
Beispiel #4
0
def validate_submission(request, code):
    """
    Validate a submission (via an emailed link to the user).

    From BSD licensed code, James Bennett
    https://bitbucket.org/ubernostrum/django-registration/src/58eef8330b0f/registration/models.py
    """
    SHA1_RE = re.compile('^[a-f0-9]{40}$')
    if SHA1_RE.search(code):
        try:
            rev = models.Revision.objects.get(validation_hash=code)
        except ObjectDoesNotExist:
            return page_404_error(request, ('That validation code was invalid'
                                            ' or used already.'))

        rev.is_displayed = True
        rev.validation_hash = None
        rev.save()
        return redirect(rev.get_absolute_url())
    else:
        return page_404_error(request, ('That validation code is invalid.'))
Beispiel #5
0
def profile_page(request, slug=None, user_id=None):
    """
    Shows the user's profile.
    """
    try:
        if user_id:
            the_user = models.User.objects.get(id=user_id)
            if the_user.is_active:
                return redirect(profile_page, the_user.profile.slug)
        elif slug is None:
            the_user = request.user
        else:
            the_user = models.User.objects.get(profile__slug=slug)
    except ObjectDoesNotExist:
        return page_404_error(request, 'No profile for that user.')

    # Don't show the profile for inactive (unvalidated) users
    if not(the_user.is_active):
        return page_404_error(request, "That user's profile isn't available.")


    # Items created by this user. Use the ``all()`` function first, to prevent
    # unvalidated submissions from showing
    all_revs = Revision.objects.all().filter(created_by=the_user)\
                                                    .order_by('-date_created')

    if the_user == request.user:
        no_entries = 'You have not submitted any entries to SciPy Central.'
    else:
        no_entries = 'This user has not submitted any entries to SciPy Central.'

    permalink = settings.SPC['short_URL_root'] + 'user/' + str(the_user.id) + '/'

    create_hit(request, the_user)
    return render_to_response('person/profile.html', {},
                context_instance=RequestContext(request,
                            {'theuser': the_user,
                             'permalink': permalink,
                             'entries':paginated_queryset(request, all_revs),
                             'no_entries_message': no_entries, }))
Beispiel #6
0
def edit_submission(request, submission, revision):

    if submission.sub_type in ['link', 'package'] and \
                                        request.user != submission.created_by:
        return page_404_error(request, ('You are not authorized to edit that '
                                        'submission. Only the original author '
                                        'may edit it.'))

    # if by POST, we are in the process of editing, so don't send the revision
    if request.POST:
        return new_or_edit_submission(request, bound_form=False)
    else:
        return new_or_edit_submission(request, bound_form=revision)
Beispiel #7
0
def profile_page_edit(request, slug):
    """
    User wants to edit his/her profile page.
    """
    # First verify that request.user is the same as slug
    if request.user.profile.slug != slug:
        return page_404_error(request,
                              ('You are not authorized to edit that '
                               'profile. Only that user may edit it.'))

    if request.POST:
        form = forms.ProfileEditForm(request.POST)
        if form.is_valid():
            # Update profile information
            user = request.user

            previous_email = ''
            if form.cleaned_data['email'] != user.email:
                previous_email = user.email
                user.email = form.cleaned_data['email']
                user.save()

            user.profile.affiliation = form.cleaned_data['affiliation']
            user.profile.country = form.cleaned_data['country']
            user.profile.bio = form.cleaned_data['bio']
            user.profile.bio_html = compile_rest_to_html(
                form.cleaned_data['bio'])
            user.profile.uri = form.cleaned_data['uri']

            user.profile.save()

            tag_list = get_and_create_tags(form.cleaned_data['interests'])

            # First delete all the user's previous interests, so we can update
            # them with the new ones
            for interest in models.InterestCreation.objects.filter(user=user):
                #.profile.interests.all():
                interest.delete()

            # Add user's interests through the intermediate
            # model instance
            for tag in tag_list:
                tag_intermediate = models.InterestCreation(user=user.profile,
                                                           tag=tag)
                tag_intermediate.save()
                logger.debug('User "%s" added interest "%s" to their profile'%\
                             (user.profile.slug, str(tag)))

            # Resave the user profile to capture their interests in the search
            # results.
            user.profile.save()

            if previous_email:
                ctx_dict = {
                    'new_email': user.email,
                    'admin_email': settings.DEFAULT_FROM_EMAIL,
                    'username': user.username
                }
                message = render_to_string(\
                              'person/email_about_changed_email_address.txt',
                              ctx_dict)
                send_email((previous_email, ), ("SciPy Central: change of "
                                                "email address"),
                           message=message)

            return redirect(profile_page, user.profile.slug)

    else:
        user = request.user
        interests = ','.join(
            list(set([str(intr) for intr in user.profile.interests.all()])))
        fields = {
            'uri': user.profile.uri,
            'email': user.email,
            'bio': user.profile.bio,
            'interests': interests,
            'country': user.profile.country,
            'affiliation': user.profile.affiliation,
            'pk': user.id,
        }
        form = forms.ProfileEditForm(fields)

    return render_to_response('submission/new-item.html', {},
                              context_instance=RequestContext(
                                  request, {
                                      'form': form,
                                      'buttontext': 'Update your profile',
                                      'pagetitle': 'Update your profile',
                                  }))
Beispiel #8
0
    def decorator(request, item_id, rev_id=None, slug=None, filename=None):
        """Retrieves the ``Submission`` and ``Revision`` objects when given,
        at a minimum the submission's primary key (``item_id``). Since the
        submission can have more than 1 revision, we can get a specific
        revision, ``rev_id``, otherwise we will always get the latest
        revision. ``slug`` is ignored for now - just used to create good SEO
        URLs.
        """
        try:
            # Use the Submissions manager's ``all()`` function
            the_submission = models.Submission.objects.all().filter(id=item_id)
        except ObjectDoesNotExist:
            return page_404_error(request, 'You request a non-existant item')

        if len(the_submission) == 0:
            return page_404_error(request, 'This item does not exist yet')

        the_submission = the_submission[0]
        the_revision = the_submission.last_revision
        if rev_id:  # can be None or '':
            all_revisions = the_submission.revisions.all()
            rev_index = int(rev_id) - 1
            if rev_index < 0:
                rev_index = len(all_revisions) - 1

            try:
                the_revision = all_revisions[rev_index]
            except (ValueError, IndexError):
                return page_404_error(request, ('The requested revision is '
                                                'non-existant.'))

        # Don't return revisions that are not approved for display yet
        if not isinstance(the_revision, models.Revision) or\
                                              not(the_revision.is_displayed):
            return page_404_error(request,
                                  "That revision isn't available yet.")

        # Is the URL of the form: "..../NN/MM/edit"; if so, then edit the item
        path_split = request.path.split('/')
        if len(path_split) > 4 and path_split[4] in ['download', 'show']:
            if path_split[4] == 'show' and len(path_split) >= 6:
                return view_function(request,
                                     the_submission,
                                     the_revision,
                                     filename=path_split[5:])
            else:
                return view_function(request, the_submission, the_revision)

        # Is the URL not the canonical URL for the item? .... redirect the user
        else:
            if rev_id is None:
                rev_id_str = '0'
                do_redirect = True
            else:
                rev_id_str = str(the_revision.rev_id + 1)
                do_redirect = False

            if slug is None or the_revision.slug != slug or do_redirect:
                return redirect('/'.join(
                    ['/item', item_id, rev_id_str, the_revision.slug]),
                                permanent=True)

        return view_function(request, the_submission, the_revision)
Beispiel #9
0
def download_submission(request, submission, revision):

    create_hit(request, submission, extra_info="download")
    if submission.sub_type == 'snippet':
        response = HttpResponse(mimetype="application/x-python")
        fname = submission.slug.replace('-', '_') + '.py'
        response["Content-Disposition"] = "attachment; filename=%s" % fname
        source = Site.objects.get_current().domain + \
                                                 submission.get_absolute_url()
        response.write('# Source: ' + source + '\n\n' + revision.item_code)
        return response

    if submission.sub_type == 'package':
        # Checkout the repo to the revision version
        checkout = submission.fileset.checkout_revision(revision.hash_id)
        if not checkout:
            logger.error('Could not checkout revision %s for rev.id %d' %
                         (revision.hash_id, revision.pk))
            return page_404_error('Could not create ZIP file. This error has '
                                  'been reported')
        logger.info('Checkout revision %s for rev.id %d' %
                    (revision.hash_id, revision.pk))

        package_data = StringIO()
        zipf = zipfile.ZipFile(package_data, 'w', zipfile.ZIP_DEFLATED)

        full_repo_path = os.path.abspath(
            os.path.join(settings.SPC['storage_dir'],
                         submission.fileset.repo_path))
        for path, dirs, files in os.walk(full_repo_path):
            # ignore revision backend dir
            if os.path.split(
                    path)[1] == '.' + settings.SPC['revisioning_backend']:
                for entry in dirs[:]:
                    dirs.remove(entry)
                continue

            for name in files:
                full_name = os.path.abspath(os.path.join(path, name))
                zipf.write(full_name, full_name.partition(full_repo_path)[2])

        for name in zipf.filelist:
            name.create_system = 0

        zipf.close()

        package_data.seek(0)

        response = HttpResponse(mimetype='attachment; application/zip')
        response['Content-Disposition'] = 'filename=%s-%d-%d.zip' \
                                          % (submission.slug, submission.pk,
                                             revision.rev_id_human)
        response.write(package_data.read())

        package_data.close()

        # checkout the repo to latest revision
        last_revision = submission.last_revision
        checkout = submission.fileset.checkout_revision(last_revision.hash_id)
        if not checkout:
            logger.error('Could not checkout out revision %s for  rev.id %d' %
                         (last_revision.hash_id, last_revision.pk))

        return response
Beispiel #10
0
    def decorator(request, item_id, rev_id=None, slug=None, filename=None):
        """Retrieves the ``Submission`` and ``Revision`` objects when given,
        at a minimum the submission's primary key (``item_id``). Since the
        submission can have more than 1 revision, we can get a specific
        revision, ``rev_id``, otherwise we will always get the latest
        revision. ``slug`` is ignored for now - just used to create good SEO
        URLs.
        """
        try:
            # Use the Submissions manager's ``all()`` function
            the_submission = models.Submission.objects.all().filter(id=item_id)
        except ObjectDoesNotExist:
            return page_404_error(request, 'You request a non-existant item')

        if len(the_submission) == 0:
            return page_404_error(request, 'This item does not exist yet')

        the_submission = the_submission[0]
        the_revision = the_submission.last_revision
        if rev_id: # can be None or '':
            all_revisions = the_submission.revisions.all()
            rev_index = int(rev_id)-1
            if rev_index < 0:
                rev_index = len(all_revisions)-1

            try:
                the_revision = all_revisions[rev_index]
            except (ValueError, IndexError):
                return page_404_error(request, ('The requested revision is '
                                                 'non-existant.'))

        # Don't return revisions that are not approved for display yet
        if not isinstance(the_revision, models.Revision) or\
                                              not(the_revision.is_displayed):
            return page_404_error(request, "That revision isn't available yet.")

        # Is the URL of the form: "..../NN/MM/edit"; if so, then edit the item
        path_split = request.path.split('/')
        if len(path_split)>4 and path_split[4] in ['edit', 'download', 'show']:
            if path_split[4] == 'show' and len(path_split)>=6:
                return view_function(request, the_submission, the_revision,
                                     filename=path_split[5:])
            else:
                return view_function(request, the_submission, the_revision)

        # Is the URL not the canonical URL for the item? .... redirect the user
        else:
            if rev_id is None:
                rev_id_str = '0'
                do_redirect = True
            else:
                rev_id_str = str(the_revision.rev_id+1)
                do_redirect = False

            if slug is None or the_revision.slug != slug or do_redirect:
                return redirect('/'.join(['/item',
                                          item_id,
                                          rev_id_str,
                                          the_revision.slug]),
                                permanent=True)


        return view_function(request, the_submission, the_revision)
Beispiel #11
0
def download_submission(request, submission, revision):

    create_hit(request, submission, extra_info="download")
    if submission.sub_type == 'snippet':
        response = HttpResponse(mimetype="application/x-python")
        fname = submission.slug.replace('-', '_') + '.py'
        response["Content-Disposition"] = "attachment; filename=%s" % fname
        source = Site.objects.get_current().domain + \
                                                 submission.get_absolute_url()
        response.write('# Source: ' + source + '\n\n' + revision.item_code)
        return response

    if submission.sub_type == 'package':
        # Checkout the repo to the revision version
        checkout = submission.fileset.checkout_revision(revision.hash_id)
        if not checkout:
            logger.error('Could not checkout revision %s for rev.id %d' 
                         % (revision.hash_id, revision.pk))
            return page_404_error('Could not create ZIP file. This error has '
                                  'been reported')
        logger.info('Checkout revision %s for rev.id %d' % (revision.hash_id, revision.pk))

        package_data = StringIO()
        zipf = zipfile.ZipFile(package_data, 'w', zipfile.ZIP_DEFLATED)

        full_repo_path = os.path.abspath(os.path.join(settings.SPC['storage_dir'],
                                                      submission.fileset.repo_path))
        for path, dirs, files in os.walk(full_repo_path):
            # ignore revision backend dir
            if os.path.split(path)[1] == '.' + settings.SPC['revisioning_backend']:
                for entry in dirs[:]:
                    dirs.remove(entry)
                continue

            for name in files:
                full_name = os.path.abspath(os.path.join(path, name))
                zipf.write(full_name, full_name.partition(full_repo_path)[2])

        for name in zipf.filelist:
            name.create_system = 0

        zipf.close()

        package_data.seek(0)

        response = HttpResponse(mimetype='attachment; application/zip')
        response['Content-Disposition'] = 'filename=%s-%d-%d.zip' \
                                          % (submission.slug, submission.pk, 
                                             revision.rev_id_human)
        response.write(package_data.read())

        package_data.close()

        # checkout the repo to latest revision
        last_revision = submission.last_revision
        checkout = submission.fileset.checkout_revision(last_revision.hash_id)
        if not checkout:
            logger.error('Could not checkout out revision %s for  rev.id %d' 
                         % (last_revision.hash_id, last_revision.pk))

        return response
Beispiel #12
0
def profile_page_edit(request, slug):
    """
    User wants to edit his/her profile page.
    """
    # First verify that request.user is the same as slug
    if request.user.profile.slug != slug:
        return page_404_error(request, ('You are not authorized to edit that '
                                        'profile. Only that user may edit it.'))


    if request.POST:
        form = forms.ProfileEditForm(request.POST)
        if form.is_valid():
            # Update profile information
            user = request.user

            previous_email = ''
            if form.cleaned_data['email'] != user.email:
                previous_email = user.email
                user.email = form.cleaned_data['email']
                user.save()

            user.profile.affiliation = form.cleaned_data['affiliation']
            user.profile.country = form.cleaned_data['country']
            user.profile.bio = form.cleaned_data['bio']
            user.profile.bio_html = compile_rest_to_html(form.cleaned_data['bio'])
            user.profile.uri = form.cleaned_data['uri']

            user.profile.save()

            tag_list = get_and_create_tags(form.cleaned_data['interests'])

            # First delete all the user's previous interests, so we can update
            # them with the new ones
            for interest in models.InterestCreation.objects.filter(user=user):
                #.profile.interests.all():
                interest.delete()

            # Add user's interests through the intermediate
            # model instance
            for tag in tag_list:
                tag_intermediate = models.InterestCreation(user=user.profile,
                                                           tag=tag)
                tag_intermediate.save()
                logger.debug('User "%s" added interest "%s" to their profile'%\
                             (user.profile.slug, str(tag)))

            # Resave the user profile to capture their interests in the search
            # results.
            user.profile.save()

            if previous_email:
                ctx_dict = {'new_email': user.email,
                            'admin_email': settings.DEFAULT_FROM_EMAIL,
                            'username': user.username}
                message = render_to_string(\
                              'person/email_about_changed_email_address.txt',
                              ctx_dict)
                send_email((previous_email,), ("SciPy Central: change of "
                                        "email address"), message=message)


            return redirect(profile_page, user.profile.slug)

    else:
        user = request.user
        interests = ','.join(list(set([str(intr) for intr in user.profile.interests.all()])))
        fields =  {'uri': user.profile.uri,
                   'email': user.email,
                   'bio': user.profile.bio,
                   'interests': interests,
                   'country': user.profile.country,
                   'affiliation': user.profile.affiliation,
                   'pk': user.id,
                   }
        form = forms.ProfileEditForm(fields)

    return render_to_response('submission/new-item.html', {},
                          context_instance=RequestContext(request,
                                {'form': form,
                                 'buttontext': 'Update your profile',
                                 'pagetitle': 'Update your profile',
                                }))
Beispiel #13
0
def create_or_edit_submission_revision(request, item, is_displayed,
                                             user, commit=False, ):
    """
    Creates a new ``Submission`` and ``Revision`` instance. Returns these in
    a tuple.
    """

    # NOTE: the ``user`` will always be a valid entry in our database. Code
    # posted by users that have not yet validated themselves is not displayed
    # until they do so.

    if item.cleaned_data['pk']:
        # We are editing an existing submission: pull it from the DB
        try:
            sub = models.Submission.objects.get(id=item.cleaned_data['pk'])
        except ObjectDoesNotExist:
            logger.error('Submission was not found when requesting "%s"' %\
                         request.path)
            page_404_error(request, ('You requested an invalid submission to '
                                     'edit'))
    else:
        # A new submission
        sub = models.Submission.objects.create_without_commit(created_by=user,
                                    sub_type=item.cleaned_data['sub_type'])


    # Process any tags
    tag_list = get_and_create_tags(item.cleaned_data['sub_tags'])

    # Create a ``Revision`` instance. Must always have a ``title``,
    # ``created_by``, and ``description`` fields; the rest are set according
    # to the submission type, ``sub.sub_type``
    hash_id = ''
    if sub.sub_type == 'link':
        sub_license = None
        item_url = item.cleaned_data['item_url']
        item_code = None
    elif sub.sub_type == 'snippet':
        sub_license = item.cleaned_data['sub_license']
        item_url = None
        item_code = item.cleaned_data['snippet_code']
    elif sub.sub_type == 'package':
        sub_license = item.cleaned_data['sub_license']
        item_url = None
        item_code = None

        # Handle the ZIP file more completely only when the user commits.
        # ZIP file has been validated: OK to save it to the server
        # However, this might be the second time around, so skip saving it
        # (happens after preview, or if user resumes editing submission)
        if not hasattr(request.FILES['package_file'], 'skip_validation'):
            zip_f = models.ZipFile(raw_zip_file=request.FILES['package_file'],
                                zip_hash=request.POST.get('package_hash', ''))
            zip_f.save()


    # Convert the raw ReST description to HTML using Sphinx: could include
    # math, paragraphs, <tt>, bold, italics, bullets, hyperlinks, etc.
    description_html = compile_rest_to_html(item.cleaned_data['description'])
    item_highlighted_code = highlight_code(item.cleaned_data.get(\
                                                        'snippet_code', None))
    rev = models.Revision.objects.create_without_commit(
                            entry=sub,
                            title=item.cleaned_data['title'],
                            created_by=user,
                            sub_license=sub_license,
                            description=item.cleaned_data['description'],
                            description_html=description_html,
                            hash_id=hash_id,
                            item_url=item_url,
                            item_code=item_code,
                            item_highlighted_code=item_highlighted_code,
                            is_displayed=is_displayed,
                            )

    user_url = settings.SPC['short_URL_root'] + 'user/' + str(user.id)
    if commit:
        # Save the submission, then the revision. If we have a primary key
        # (case happens when user is editing a previous submission), then
        # do not save the submission (because the Submission object has fields
        # that will never change once it has been first created). Only set
        # the ``pk`` so that the new revision object is correct.
        if item.cleaned_data['pk']:
            # We are updating an existing ``sub`` item (see code above)
            pass
        else:
            sub.save()

        rev.entry_id = sub.id
        if not is_displayed:
            rev.validation_hash = create_validation_code(rev)

        rev.save()

        # Storage location: if we do save files it will be here
        datenow = datetime.datetime.now()
        year, month = datenow.strftime('%Y'), datenow.strftime('%m')
        repo_path = os.path.join(year, month, '%06d'% sub.id)
        full_repo_path = os.path.join(settings.SPC['storage_dir'], repo_path)


        if sub.sub_type == 'package':
            # Save the uploaded file to the server. At this point we are sure
            # it's a valid ZIP file, has no malicious filenames, and can be
            # unpacked to the hard drive. See validation in ``forms.py``.


            if os.path.exists(full_repo_path) and sub.fileset.repo_path == \
                                                                     repo_path:
                # Make a temporary directory and copy the existing package
                # repository to that location
                temp_dir = tempfile.mkdtemp(prefix='tmp_spc_')
                src = os.path.join(full_repo_path, '.' + \
                                           settings.SPC['revisioning_backend'])
                shutil.move(src, temp_dir)
                shutil.rmtree(full_repo_path, ignore_errors=True)
            else:
                temp_dir = None

            # Create/ensure destination directory exists
            ensuredir(full_repo_path)

               # Copy ZIP file
            zip_file = request.FILES['package_file']
            dst = os.path.join(full_repo_path, zip_file.name)
            src = os.path.join(settings.SPC['ZIP_staging'], zip_file.name)
            shutil.copyfile(src, dst)
            # os.remove(src) Keep the original ZIP file, for now

            # Remove the entry from the database
            zip_hash = request.POST.get('package_hash', '')
            zip_objs = models.ZipFile.objects.filter(zip_hash=zip_hash)
            if zip_objs:
                zip_objs[0].delete()

            # Unzip file and commit contents to the repo
            zip_f = zipfile.ZipFile(dst, 'r')
            zip_f.extractall(full_repo_path)
            zip_f.close()
            os.remove(dst) # but delete the copy

            # Delete common RCS directories that might have been in the ZIP
            for path, dirs, files in os.walk(full_repo_path):
                if os.path.split(path)[1] in settings.SPC['common_rcs_dirs']:
                    shutil.rmtree(path, ignore_errors=True)


            if temp_dir:
                src = os.path.join(temp_dir, '.' + \
                                           settings.SPC['revisioning_backend'])
                dst = os.path.join(full_repo_path , '.' + \
                                           settings.SPC['revisioning_backend'])
                try:
                    os.rename(src, dst)
                except os.error, e:
                    # For cases when /tmp is on a different filesystem
                    # (usually production servers)
                    import errno
                    if e.errno == errno.EXDEV:
                        shutil.copytree(src, dst, symlinks=True)
                        shutil.rmtree(src)
                    else:
                        raise

                shutil.rmtree(temp_dir, ignore_errors=True)
                repo = sub.fileset.get_repo()
            else:
                # Create the repo
                sub.fileset = FileSet.objects.create(repo_path=repo_path)
                repo = sub.fileset.create_empty()
                sub.save()


            # Then add all files from the ZIP file to the repo. Add directories
            # at a time rather than file-by-file.
            for path, dirs, files in os.walk(full_repo_path):
                if os.path.split(path)[1] == '.' + \
                                          settings.SPC['revisioning_backend']:
                    for entry in dirs[:]:
                        dirs.remove(entry)

                    continue

                all_files = []
                for name in files:
                    all_files.append(os.path.join(path, name))

                if all_files:
                    repo.add(patterns=all_files, ignore_errors=True)


            # Add "DESCRIPTION.txt"
            descrip_name = os.path.join(full_repo_path, 'DESCRIPTION.txt')
            descrip_file = file(descrip_name, 'w')
            descrip_file.write(rev.description)
            descrip_file.close()
            sub.fileset.add_file(descrip_name, user=user_url,
                            commit_msg=('Added/updated files from web-uploaded '
                                    'ZIP file. Added DESCRIPTION.txt also.'))

        if sub.sub_type == 'snippet':
            fname = rev.slug.replace('-', '_') + '.py'
            if not item.cleaned_data['pk']:
            # Create a new repository for the files

                sub.fileset = FileSet.objects.create(repo_path=repo_path)
                sub.save()
                commit_msg = ('Add "%s" to the repo '
                              'based on the web submission by user "%s"') %\
                                                              (fname, user_url)
            else:
                commit_msg = ('Update of file(s) in the repo '
                              'based on the web submission by user "%s"') %\
                                                              (user_url)


            sub.fileset.add_file_from_string(fname,
                                             request.POST['snippet_code'],
                                             user=user_url,
                                             commit_msg=commit_msg)

        if sub.sub_type in ['snippet', 'package']:
            license_file = settings.SPC['license_filename']
            license_text = get_license_text(rev)
            sub.fileset.add_file_from_string(license_file, license_text,
                                             user="******",
                            commit_msg="SPC: added/updated license file" )
            rev.hash_id = sub.fileset.get_hash()


        # Once you have the revision you can add tags through the intermediate
        # model instance (which tracks the user that added the tag and when).
        for tag in tag_list:
            tag_intermediate = models.TagCreation(created_by=user,
                                                  revision=rev,
                                                  tag=tag)
            tag_intermediate.save()
            logger.debug('User "%s" added tag "%s" to rev.id=%d' % (
                                                user.profile.slug,
                                                str(tag), rev.id))

        # Update the search index so that the tags are included in the search
        rev.save()

        # log the new submission and revision
        logger.info('New %s: %s [id=%d] and revision id=%d' % (
                                                sub.sub_type,
                                                item.cleaned_data['title'],
                                                sub.id,
                                                rev.id))