##// END OF EJS Templates
Prefix gist storage with rc, and store some metadata info into...
marcink -
r3841:979edf6a beta
parent child Browse files
Show More
@@ -1,161 +1,173
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.gist
4 4 ~~~~~~~~~~~~~~~~~~~~
5 5
6 6 gist model for RhodeCode
7 7
8 8 :created_on: May 9, 2013
9 9 :author: marcink
10 10 :copyright: (C) 2011-2013 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25 from __future__ import with_statement
26 26 import os
27 27 import time
28 28 import logging
29 29 import traceback
30 30 import shutil
31 31
32 32 from pylons.i18n.translation import _
33 33 from rhodecode.lib.utils2 import safe_unicode, unique_id, safe_int, \
34 34 time_to_datetime, safe_str, AttributeDict
35 from rhodecode.lib.compat import json
35 36 from rhodecode.lib import helpers as h
36 37 from rhodecode.model import BaseModel
37 38 from rhodecode.model.db import Gist
38 39 from rhodecode.model.repo import RepoModel
39 40 from rhodecode.model.scm import ScmModel
40 41 from rhodecode.lib.vcs import get_repo
41 42
42 43 log = logging.getLogger(__name__)
43 44
44 GIST_STORE_LOC = '.gist_store'
45 GIST_STORE_LOC = '.rc_gist_store'
46 GIST_METADATA_FILE = '.rc_gist_metadata'
45 47
46 48
47 49 class GistModel(BaseModel):
48 50
49 51 def _get_gist(self, gist):
50 52 """
51 53 Helper method to get gist by ID, or gist_access_id as a fallback
52 54
53 55 :param gist: GistID, gist_access_id, or Gist instance
54 56 """
55 57 return self._get_instance(Gist, gist,
56 58 callback=Gist.get_by_access_id)
57 59
58 60 def __delete_gist(self, gist):
59 61 """
60 62 removes gist from filesystem
61 63
62 64 :param gist: gist object
63 65 """
64 66 root_path = RepoModel().repos_path
65 67 rm_path = os.path.join(root_path, GIST_STORE_LOC, gist.gist_access_id)
66 68 log.info("Removing %s" % (rm_path))
67 69 shutil.rmtree(rm_path)
68 70
69 71 def get_gist_files(self, gist_access_id):
70 72 """
71 73 Get files for given gist
72 74
73 75 :param gist_access_id:
74 76 """
75 77 root_path = RepoModel().repos_path
76 78 r = get_repo(os.path.join(*map(safe_str,
77 79 [root_path, GIST_STORE_LOC, gist_access_id])))
78 80 cs = r.get_changeset()
79 81 return (
80 82 cs, [n for n in cs.get_node('/')]
81 83 )
82 84
83 85 def create(self, description, owner, gist_mapping,
84 86 gist_type=Gist.GIST_PUBLIC, lifetime=-1):
85 87 """
86 88
87 89 :param description: description of the gist
88 90 :param owner: user who created this gist
89 91 :param gist_mapping: mapping {filename:{'content':content},...}
90 92 :param gist_type: type of gist private/public
91 93 :param lifetime: in minutes, -1 == forever
92 94 """
93 95 gist_id = safe_unicode(unique_id(20))
94 96 lifetime = safe_int(lifetime, -1)
95 97 gist_expires = time.time() + (lifetime * 60) if lifetime != -1 else -1
96 98 log.debug('set GIST expiration date to: %s'
97 99 % (time_to_datetime(gist_expires)
98 100 if gist_expires != -1 else 'forever'))
99 101 #create the Database version
100 102 gist = Gist()
101 103 gist.gist_description = description
102 104 gist.gist_access_id = gist_id
103 105 gist.gist_owner = owner.user_id
104 106 gist.gist_expires = gist_expires
105 107 gist.gist_type = safe_unicode(gist_type)
106 108 self.sa.add(gist)
107 109 self.sa.flush()
108 110 if gist_type == Gist.GIST_PUBLIC:
109 111 # use DB ID for easy to use GIST ID
110 112 gist_id = safe_unicode(gist.gist_id)
111 113 gist.gist_access_id = gist_id
112 114 self.sa.add(gist)
113 115
114 116 gist_repo_path = os.path.join(GIST_STORE_LOC, gist_id)
115 117 log.debug('Creating new %s GIST repo in %s' % (gist_type, gist_repo_path))
116 118 repo = RepoModel()._create_repo(repo_name=gist_repo_path, alias='hg',
117 119 parent=None)
118 120
119 121 processed_mapping = {}
120 122 for filename in gist_mapping:
121 123 content = gist_mapping[filename]['content']
122 124 #TODO: expand support for setting explicit lexers
123 125 # if lexer is None:
124 126 # try:
125 127 # lexer = pygments.lexers.guess_lexer_for_filename(filename,content)
126 128 # except pygments.util.ClassNotFound:
127 129 # lexer = 'text'
128 130 processed_mapping[filename] = {'content': content}
129 131
130 132 # now create single multifile commit
131 133 message = 'added file'
132 134 message += 's: ' if len(processed_mapping) > 1 else ': '
133 135 message += ', '.join([x for x in processed_mapping])
134 136
135 137 #fake RhodeCode Repository object
136 138 fake_repo = AttributeDict(dict(
137 139 repo_name=gist_repo_path,
138 140 scm_instance_no_cache=lambda: repo,
139 141 ))
140 142 ScmModel().create_nodes(
141 143 user=owner.user_id, repo=fake_repo,
142 144 message=message,
143 145 nodes=processed_mapping,
144 146 trigger_push_hook=False
145 147 )
146
148 # store metadata inside the gist, this can be later used for imports
149 # or gist identification
150 metadata = {
151 'gist_db_id': gist.gist_id,
152 'gist_access_id': gist.gist_access_id,
153 'gist_owner_id': owner.user_id,
154 'gist_type': gist.gist_type,
155 'gist_exipres': gist.gist_expires
156 }
157 with open(os.path.join(repo.path, '.hg', GIST_METADATA_FILE), 'wb') as f:
158 f.write(json.dumps(metadata))
147 159 return gist
148 160
149 161 def delete(self, gist, fs_remove=True):
150 162 gist = self._get_gist(gist)
151 163
152 164 try:
153 165 self.sa.delete(gist)
154 166 if fs_remove:
155 167 self.__delete_gist(gist)
156 168 else:
157 169 log.debug('skipping removal from filesystem')
158 170
159 171 except Exception:
160 172 log.error(traceback.format_exc())
161 173 raise
General Comments 0
You need to be logged in to leave comments. Login now