diff --git a/rhodecode/model/gist.py b/rhodecode/model/gist.py --- a/rhodecode/model/gist.py +++ b/rhodecode/model/gist.py @@ -1,15 +1,4 @@ # -*- coding: utf-8 -*- -""" - rhodecode.model.gist - ~~~~~~~~~~~~~~~~~~~~ - - gist model for RhodeCode - - :created_on: May 9, 2013 - :author: marcink - :copyright: (C) 2011-2013 Marcin Kuzminski - :license: GPLv3, see COPYING for more details. -""" # 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 @@ -22,6 +11,18 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +rhodecode.model.gist +~~~~~~~~~~~~~~~~~~~~ + +gist model for RhodeCode + +:created_on: May 9, 2013 +:author: marcink +:copyright: (c) 2013 RhodeCode GmbH. +:license: GPLv3, see LICENSE for more details. +""" + from __future__ import with_statement import os import time @@ -46,6 +47,7 @@ GIST_METADATA_FILE = '.rc_gist_metadata' class GistModel(BaseModel): + cls = Gist def _get_gist(self, gist): """ @@ -53,8 +55,7 @@ class GistModel(BaseModel): :param gist: GistID, gist_access_id, or Gist instance """ - return self._get_instance(Gist, gist, - callback=Gist.get_by_access_id) + return self._get_instance(Gist, gist, callback=Gist.get_by_access_id) def __delete_gist(self, gist): """ @@ -64,23 +65,39 @@ class GistModel(BaseModel): """ root_path = RepoModel().repos_path rm_path = os.path.join(root_path, GIST_STORE_LOC, gist.gist_access_id) - log.info("Removing %s" % (rm_path)) + log.info("Removing %s" % (rm_path,)) 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: + f.write(json.dumps(metadata)) + def get_gist(self, gist): return self._get_gist(gist) - def get_gist_files(self, gist_access_id): + 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() - return ( - cs, [n for n in cs.get_node('/')] - ) + cs = repo.scm_instance.get_changeset(revision) + return cs, [n for n in cs.get_node('/')] def create(self, description, owner, gist_mapping, gist_type=Gist.GIST_PUBLIC, lifetime=-1): @@ -92,6 +109,7 @@ class GistModel(BaseModel): :param gist_type: type of gist private/public :param lifetime: in minutes, -1 == forever """ + owner = self._get_user(owner) gist_id = safe_unicode(unique_id(20)) lifetime = safe_int(lifetime, -1) gist_expires = time.time() + (lifetime * 60) if lifetime != -1 else -1 @@ -115,8 +133,8 @@ class GistModel(BaseModel): gist_repo_path = os.path.join(GIST_STORE_LOC, gist_id) log.debug('Creating new %s GIST repo in %s' % (gist_type, gist_repo_path)) - repo = RepoModel()._create_repo(repo_name=gist_repo_path, alias='hg', - parent=None) + repo = RepoModel()._create_filesystem_repo( + repo_name=gist_id, repo_type='hg', repo_group=GIST_STORE_LOC) processed_mapping = {} for filename in gist_mapping: @@ -127,7 +145,8 @@ class GistModel(BaseModel): #TODO: expand support for setting explicit lexers # if lexer is None: # try: -# lexer = pygments.lexers.guess_lexer_for_filename(filename,content) +# guess_lexer = pygments.lexers.guess_lexer_for_filename +# lexer = guess_lexer(filename,content) # except pygments.util.ClassNotFound: # lexer = 'text' processed_mapping[filename] = {'content': content} @@ -148,29 +167,74 @@ class GistModel(BaseModel): nodes=processed_mapping, trigger_push_hook=False ) - # store metadata inside the gist, this can be later used for imports - # or gist identification - metadata = { - 'gist_db_id': gist.gist_id, - 'gist_access_id': gist.gist_access_id, - 'gist_owner_id': owner.user_id, - 'gist_type': gist.gist_type, - 'gist_exipres': gist.gist_expires - } - with open(os.path.join(repo.path, '.hg', GIST_METADATA_FILE), 'wb') as f: - f.write(json.dumps(metadata)) + + 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): gist = self._get_gist(gist) - try: self.sa.delete(gist) if fs_remove: self.__delete_gist(gist) else: log.debug('skipping removal from filesystem') - except Exception: log.error(traceback.format_exc()) raise + + def update(self, gist, description, owner, gist_mapping, gist_type, + lifetime): + gist = self._get_gist(gist) + 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 + + #calculate operation type based on given data + 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 + self.sa.add(gist) + self.sa.flush() + + message = 'updated file' + message += 's: ' if len(gist_mapping) > 1 else ': ' + message += ', '.join([x for x in gist_mapping]) + + #fake RhodeCode Repository object + fake_repo = AttributeDict(dict( + repo_name=gist_repo.path, + 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, + repo=fake_repo, + message=message, + nodes=gist_mapping_op, + trigger_push_hook=False + ) + + return gist