##// END OF EJS Templates
py3: some not-entirely-trivial removing of "unicode"
py3: some not-entirely-trivial removing of "unicode"

File last commit:

r8075:e3537310 default
r8080:f9988201 default
Show More
gist.py
236 lines | 8.2 KiB | text/x-python | PythonLexer
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 # -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
kallithea.model.gist
~~~~~~~~~~~~~~~~~~~~
Bradley M. Kuhn
General renaming to Kallithea
r4212 gist model for Kallithea
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Bradley M. Kuhn
RhodeCode GmbH is not the sole author of this work
r4211 This file was forked by the Kallithea project in July 2014.
Original author and date, and relevant copyright and licensing information is below:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 :created_on: May 9, 2013
:author: marcink
Bradley M. Kuhn
RhodeCode GmbH is not the sole author of this work
r4211 :copyright: (c) 2013 RhodeCode GmbH, and others.
Bradley M. Kuhn
Correct licensing information in individual files....
r4208 :license: GPLv3, see LICENSE.md for more details.
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 import logging
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 import os
Søren Løvborg
model: greatly simplify generation of gist IDs...
r6457 import random
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 import shutil
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 import time
import traceback
Mads Kiilerich
lib: clean up ext_json and how it is used - avoid monkey patching...
r7987 from kallithea.lib import ext_json
Mads Kiilerich
py3: remove safe_unicode in places where it no longer is needed because all strings (except bytes) already *are* unicode strings...
r8075 from kallithea.lib.utils2 import AttributeDict, ascii_bytes, safe_int, time_to_datetime
Søren Løvborg
model: remove BaseModel class...
r6483 from kallithea.model.db import Gist, Session, User
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 from kallithea.model.repo import RepoModel
from kallithea.model.scm import ScmModel
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 log = logging.getLogger(__name__)
GIST_STORE_LOC = '.rc_gist_store'
GIST_METADATA_FILE = '.rc_gist_metadata'
Mads Kiilerich
gist: make it a bit more clear how gist_access_id is used ... and how it is different from gist_id...
r7951 def make_gist_access_id():
Søren Løvborg
model: greatly simplify generation of gist IDs...
r6457 """Generate a random, URL safe, almost certainly unique gist identifier."""
rnd = random.SystemRandom() # use cryptographically secure system PRNG
alphabet = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjklmnpqrstuvwxyz'
length = 20
Mads Kiilerich
py3: automatic migration with 2to3 -f xrange
r8061 return u''.join(rnd.choice(alphabet) for _ in range(length))
Søren Løvborg
model: greatly simplify generation of gist IDs...
r6457
Søren Løvborg
model: remove BaseModel class...
r6483 class GistModel(object):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def __delete_gist(self, gist):
"""
removes gist from filesystem
:param gist: gist object
"""
root_path = RepoModel().repos_path
rm_path = os.path.join(root_path, GIST_STORE_LOC, gist.gist_access_id)
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.info("Removing %s", rm_path)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 shutil.rmtree(rm_path)
def _store_metadata(self, repo, gist_id, gist_access_id, user_id, gist_type,
gist_expires):
"""
store metadata inside the gist, this can be later used for imports
or gist identification
"""
metadata = {
'metadata_version': '1',
'gist_db_id': gist_id,
'gist_access_id': gist_access_id,
'gist_owner_id': user_id,
'gist_type': gist_type,
'gist_expires': gist_expires,
'gist_updated': time.time(),
}
with open(os.path.join(repo.path, '.hg', GIST_METADATA_FILE), 'wb') as f:
Mads Kiilerich
lib: clean up ext_json and how it is used - avoid monkey patching...
r7987 f.write(ascii_bytes(ext_json.dumps(metadata)))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def get_gist(self, gist):
Søren Løvborg
model: inline GistModel._get_gist calls
r6427 return Gist.guess_instance(gist)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def get_gist_files(self, gist_access_id, revision=None):
"""
Get files for given gist
:param gist_access_id:
"""
repo = Gist.get_by_access_id(gist_access_id)
cs = repo.scm_instance.get_changeset(revision)
return cs, [n for n in cs.get_node('/')]
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 def create(self, description, owner, ip_addr, gist_mapping,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 gist_type=Gist.GIST_PUBLIC, lifetime=-1):
"""
:param description: description of the gist
:param owner: user who created this gist
:param gist_mapping: mapping {filename:{'content':content},...}
:param gist_type: type of gist private/public
:param lifetime: in minutes, -1 == forever
"""
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 owner = User.guess_instance(owner)
Mads Kiilerich
gist: make it a bit more clear how gist_access_id is used ... and how it is different from gist_id...
r7951 gist_access_id = make_gist_access_id()
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 lifetime = safe_int(lifetime, -1)
gist_expires = time.time() + (lifetime * 60) if lifetime != -1 else -1
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.debug('set GIST expiration date to: %s',
time_to_datetime(gist_expires)
if gist_expires != -1 else 'forever')
Lars Kruse
codingstyle: trivial whitespace fixes...
r6789 # create the Database version
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 gist = Gist()
gist.gist_description = description
Mads Kiilerich
gist: make it a bit more clear how gist_access_id is used ... and how it is different from gist_id...
r7951 gist.gist_access_id = gist_access_id
Søren Løvborg
db: rename Gist.gist_owner to Gist.owner_id...
r6283 gist.owner_id = owner.user_id
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 gist.gist_expires = gist_expires
Mads Kiilerich
py3: remove safe_unicode in places where it no longer is needed because all strings (except bytes) already *are* unicode strings...
r8075 gist.gist_type = gist_type
Søren Løvborg
model: remove BaseModel class...
r6483 Session().add(gist)
Session().flush() # make database assign gist.gist_id
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 if gist_type == Gist.GIST_PUBLIC:
# use DB ID for easy to use GIST ID
Mads Kiilerich
gist: make it a bit more clear how gist_access_id is used ... and how it is different from gist_id...
r7951 gist.gist_access_id = unicode(gist.gist_id)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
gist: make it a bit more clear how gist_access_id is used ... and how it is different from gist_id...
r7951 log.debug('Creating new %s GIST repo %s', gist_type, gist.gist_access_id)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 repo = RepoModel()._create_filesystem_repo(
Mads Kiilerich
gist: make it a bit more clear how gist_access_id is used ... and how it is different from gist_id...
r7951 repo_name=gist.gist_access_id, repo_type='hg', repo_group=GIST_STORE_LOC)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
processed_mapping = {}
for filename in gist_mapping:
if filename != os.path.basename(filename):
raise Exception('Filename cannot be inside a directory')
content = gist_mapping[filename]['content']
Lars Kruse
codingstyle: trivial whitespace fixes...
r6789 # TODO: expand support for setting explicit lexers
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 # if lexer is None:
# try:
# guess_lexer = pygments.lexers.guess_lexer_for_filename
# lexer = guess_lexer(filename,content)
# except pygments.util.ClassNotFound:
# lexer = 'text'
processed_mapping[filename] = {'content': content}
# now create single multifile commit
message = 'added file'
message += 's: ' if len(processed_mapping) > 1 else ': '
message += ', '.join([x for x in processed_mapping])
Lars Kruse
codingstyle: trivial whitespace fixes...
r6789 # fake Kallithea Repository object
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 fake_repo = AttributeDict(dict(
Mads Kiilerich
gist: make it a bit more clear how gist_access_id is used ... and how it is different from gist_id...
r7951 repo_name=os.path.join(GIST_STORE_LOC, gist.gist_access_id),
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 scm_instance_no_cache=lambda: repo,
))
ScmModel().create_nodes(
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 user=owner.user_id,
ip_addr=ip_addr,
repo=fake_repo,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 message=message,
nodes=processed_mapping,
trigger_push_hook=False
)
self._store_metadata(repo, gist.gist_id, gist.gist_access_id,
owner.user_id, gist.gist_type, gist.gist_expires)
return gist
def delete(self, gist, fs_remove=True):
Søren Løvborg
model: inline GistModel._get_gist calls
r6427 gist = Gist.guess_instance(gist)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 try:
Søren Løvborg
model: remove BaseModel class...
r6483 Session().delete(gist)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 if fs_remove:
self.__delete_gist(gist)
else:
log.debug('skipping removal from filesystem')
except Exception:
log.error(traceback.format_exc())
raise
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 def update(self, gist, description, owner, ip_addr, gist_mapping, gist_type,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 lifetime):
Søren Løvborg
model: inline GistModel._get_gist calls
r6427 gist = Gist.guess_instance(gist)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 gist_repo = gist.scm_instance
lifetime = safe_int(lifetime, -1)
if lifetime == 0: # preserve old value
gist_expires = gist.gist_expires
else:
gist_expires = time.time() + (lifetime * 60) if lifetime != -1 else -1
Lars Kruse
codingstyle: trivial whitespace fixes...
r6789 # calculate operation type based on given data
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 gist_mapping_op = {}
for k, v in gist_mapping.items():
# add, mod, del
if not v['org_filename'] and v['filename']:
op = 'add'
elif v['org_filename'] and not v['filename']:
op = 'del'
else:
op = 'mod'
v['op'] = op
gist_mapping_op[k] = v
gist.gist_description = description
gist.gist_expires = gist_expires
gist.owner = owner
gist.gist_type = gist_type
message = 'updated file'
message += 's: ' if len(gist_mapping) > 1 else ': '
message += ', '.join([x for x in gist_mapping])
Lars Kruse
codingstyle: trivial whitespace fixes...
r6789 # fake Kallithea Repository object
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 fake_repo = AttributeDict(dict(
Mads Kiilerich
gist: make it a bit more clear how gist_access_id is used ... and how it is different from gist_id...
r7951 repo_name=os.path.join(GIST_STORE_LOC, gist.gist_access_id),
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 scm_instance_no_cache=lambda: gist_repo,
))
self._store_metadata(gist_repo, gist.gist_id, gist.gist_access_id,
owner.user_id, gist.gist_type, gist.gist_expires)
ScmModel().update_nodes(
user=owner.user_id,
Mads Kiilerich
scm: don't try to get IP address from web request in model...
r7632 ip_addr=ip_addr,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 repo=fake_repo,
message=message,
nodes=gist_mapping_op,
trigger_push_hook=False
)
return gist