##// END OF EJS Templates
archvies: allowing to obtain archives without the commit short id in the name for better automation of obtained artifacts.
milka -
r4534:5ad2c43b default
parent child Browse files
Show More
@@ -325,6 +325,21 b' class RepoFilesView(RepoAppView):'
325
325
326 return lf_enabled
326 return lf_enabled
327
327
328 def _get_archive_name(self, db_repo_name, commit_sha, ext, subrepos=False, path_sha=''):
329 # original backward compat name of archive
330 clean_name = safe_str(db_repo_name.replace('/', '_'))
331
332 # e.g vcsserver.zip
333 # e.g vcsserver-abcdefgh.zip
334 # e.g vcsserver-abcdefgh-defghijk.zip
335 archive_name = '{}{}{}{}{}'.format(
336 clean_name,
337 '-sub' if subrepos else '',
338 commit_sha,
339 '-{}'.format(path_sha) if path_sha else '',
340 ext)
341 return archive_name
342
328 @LoginRequired()
343 @LoginRequired()
329 @HasRepoPermissionAnyDecorator(
344 @HasRepoPermissionAnyDecorator(
330 'repository.read', 'repository.write', 'repository.admin')
345 'repository.read', 'repository.write', 'repository.admin')
@@ -339,6 +354,7 b' class RepoFilesView(RepoAppView):'
339 default_at_path = '/'
354 default_at_path = '/'
340 fname = self.request.matchdict['fname']
355 fname = self.request.matchdict['fname']
341 subrepos = self.request.GET.get('subrepos') == 'true'
356 subrepos = self.request.GET.get('subrepos') == 'true'
357 with_hash = str2bool(self.request.GET.get('with_hash', '1'))
342 at_path = self.request.GET.get('at_path') or default_at_path
358 at_path = self.request.GET.get('at_path') or default_at_path
343
359
344 if not self.db_repo.enable_downloads:
360 if not self.db_repo.enable_downloads:
@@ -364,26 +380,26 b' class RepoFilesView(RepoAppView):'
364 except Exception:
380 except Exception:
365 return Response(_('No node at path {} for this repository').format(at_path))
381 return Response(_('No node at path {} for this repository').format(at_path))
366
382
383 # path sha is part of subdir
384 path_sha = ''
385 if at_path != default_at_path:
367 path_sha = sha1(at_path)[:8]
386 path_sha = sha1(at_path)[:8]
368
387 short_sha = '-{}'.format(safe_str(commit.short_id))
369 # original backward compat name of archive
388 # used for cache etc
370 clean_name = safe_str(self.db_repo_name.replace('/', '_'))
389 archive_name = self._get_archive_name(
371 short_sha = safe_str(commit.short_id)
390 self.db_repo_name, commit_sha=short_sha, ext=ext, subrepos=subrepos,
391 path_sha=path_sha)
372
392
373 if at_path == default_at_path:
393 if not with_hash:
374 archive_name = '{}-{}{}{}'.format(
394 short_sha = ''
375 clean_name,
395 path_sha = ''
376 '-sub' if subrepos else '',
396
377 short_sha,
397 # what end client gets served
378 ext)
398 response_archive_name = self._get_archive_name(
379 # custom path and new name
399 self.db_repo_name, commit_sha=short_sha, ext=ext, subrepos=subrepos,
380 else:
400 path_sha=path_sha)
381 archive_name = '{}-{}{}-{}{}'.format(
401 # remove extension from our archive directory name
382 clean_name,
402 archive_dir_name = response_archive_name[:-len(ext)]
383 '-sub' if subrepos else '',
384 short_sha,
385 path_sha,
386 ext)
387
403
388 use_cached_archive = False
404 use_cached_archive = False
389 archive_cache_enabled = CONFIG.get(
405 archive_cache_enabled = CONFIG.get(
@@ -403,13 +419,15 b' class RepoFilesView(RepoAppView):'
403 else:
419 else:
404 log.debug('Archive %s is not yet cached', archive_name)
420 log.debug('Archive %s is not yet cached', archive_name)
405
421
422 # generate new archive, as previous was not found in the cache
406 if not use_cached_archive:
423 if not use_cached_archive:
407 # generate new archive
424
408 fd, archive = tempfile.mkstemp()
425 fd, archive = tempfile.mkstemp()
409 log.debug('Creating new temp archive in %s', archive)
426 log.debug('Creating new temp archive in %s', archive)
410 try:
427 try:
411 commit.archive_repo(archive, kind=fileformat, subrepos=subrepos,
428 commit.archive_repo(archive, archive_dir_name=archive_dir_name,
412 archive_at_path=at_path)
429 kind=fileformat, subrepos=subrepos,
430 archive_at_path=at_path, with_hash=with_hash)
413 except ImproperArchiveTypeError:
431 except ImproperArchiveTypeError:
414 return _('Unknown archive type')
432 return _('Unknown archive type')
415 if archive_cache_enabled:
433 if archive_cache_enabled:
@@ -445,8 +463,7 b' class RepoFilesView(RepoAppView):'
445 yield data
463 yield data
446
464
447 response = Response(app_iter=get_chunked_archive(archive))
465 response = Response(app_iter=get_chunked_archive(archive))
448 response.content_disposition = str(
466 response.content_disposition = str('attachment; filename=%s' % response_archive_name)
449 'attachment; filename=%s' % archive_name)
450 response.content_type = str(content_type)
467 response.content_type = str(content_type)
451
468
452 return response
469 return response
@@ -1192,13 +1192,14 b' class BaseCommit(object):'
1192 return None
1192 return None
1193
1193
1194 def archive_repo(self, archive_dest_path, kind='tgz', subrepos=None,
1194 def archive_repo(self, archive_dest_path, kind='tgz', subrepos=None,
1195 prefix=None, write_metadata=False, mtime=None, archive_at_path='/'):
1195 archive_dir_name=None, write_metadata=False, mtime=None,
1196 archive_at_path='/', with_hash=True):
1196 """
1197 """
1197 Creates an archive containing the contents of the repository.
1198 Creates an archive containing the contents of the repository.
1198
1199
1199 :param archive_dest_path: path to the file which to create the archive.
1200 :param archive_dest_path: path to the file which to create the archive.
1200 :param kind: one of following: ``"tbz2"``, ``"tgz"``, ``"zip"``.
1201 :param kind: one of following: ``"tbz2"``, ``"tgz"``, ``"zip"``.
1201 :param prefix: name of root directory in archive.
1202 :param archive_dir_name: name of root directory in archive.
1202 Default is repository name and commit's short_id joined with dash:
1203 Default is repository name and commit's short_id joined with dash:
1203 ``"{repo_name}-{short_id}"``.
1204 ``"{repo_name}-{short_id}"``.
1204 :param write_metadata: write a metadata file into archive.
1205 :param write_metadata: write a metadata file into archive.
@@ -1214,7 +1215,7 b' class BaseCommit(object):'
1214 'Archive kind (%s) not supported use one of %s' %
1215 'Archive kind (%s) not supported use one of %s' %
1215 (kind, allowed_kinds))
1216 (kind, allowed_kinds))
1216
1217
1217 prefix = self._validate_archive_prefix(prefix)
1218 archive_dir_name = self._validate_archive_prefix(archive_dir_name)
1218
1219
1219 mtime = mtime is not None or time.mktime(self.date.timetuple())
1220 mtime = mtime is not None or time.mktime(self.date.timetuple())
1220
1221
@@ -1222,7 +1223,7 b' class BaseCommit(object):'
1222 cur_rev = self.repository.get_commit(commit_id=self.raw_id)
1223 cur_rev = self.repository.get_commit(commit_id=self.raw_id)
1223 for _r, _d, files in cur_rev.walk(archive_at_path):
1224 for _r, _d, files in cur_rev.walk(archive_at_path):
1224 for f in files:
1225 for f in files:
1225 f_path = os.path.join(prefix, f.path)
1226 f_path = os.path.join(archive_dir_name, f.path)
1226 file_info.append(
1227 file_info.append(
1227 (f_path, f.mode, f.is_link(), f.raw_bytes))
1228 (f_path, f.mode, f.is_link(), f.raw_bytes))
1228
1229
@@ -1239,18 +1240,18 b' class BaseCommit(object):'
1239
1240
1240 connection.Hg.archive_repo(archive_dest_path, mtime, file_info, kind)
1241 connection.Hg.archive_repo(archive_dest_path, mtime, file_info, kind)
1241
1242
1242 def _validate_archive_prefix(self, prefix):
1243 def _validate_archive_prefix(self, archive_dir_name):
1243 if prefix is None:
1244 if archive_dir_name is None:
1244 prefix = self._ARCHIVE_PREFIX_TEMPLATE.format(
1245 archive_dir_name = self._ARCHIVE_PREFIX_TEMPLATE.format(
1245 repo_name=safe_str(self.repository.name),
1246 repo_name=safe_str(self.repository.name),
1246 short_id=self.short_id)
1247 short_id=self.short_id)
1247 elif not isinstance(prefix, str):
1248 elif not isinstance(archive_dir_name, str):
1248 raise ValueError("prefix not a bytes object: %s" % repr(prefix))
1249 raise ValueError("prefix not a bytes object: %s" % repr(archive_dir_name))
1249 elif prefix.startswith('/'):
1250 elif archive_dir_name.startswith('/'):
1250 raise VCSError("Prefix cannot start with leading slash")
1251 raise VCSError("Prefix cannot start with leading slash")
1251 elif prefix.strip() == '':
1252 elif archive_dir_name.strip() == '':
1252 raise VCSError("Prefix cannot be empty")
1253 raise VCSError("Prefix cannot be empty")
1253 return prefix
1254 return archive_dir_name
1254
1255
1255 @LazyProperty
1256 @LazyProperty
1256 def root(self):
1257 def root(self):
@@ -51,7 +51,7 b''
51 ${_('Download full tree ZIP')}
51 ${_('Download full tree ZIP')}
52 </a>
52 </a>
53 % else:
53 % else:
54 <a href="${h.route_path('repo_archivefile',repo_name=c.repo_name, fname='{}.zip'.format(c.commit.raw_id), _query={'at_path':c.f_path})}">
54 <a href="${h.route_path('repo_archivefile',repo_name=c.repo_name, fname='{}.zip'.format(c.commit.raw_id), _query={'at_path':c.f_path, 'with_hash': '1'})}">
55 ${_('Download this tree ZIP')}
55 ${_('Download this tree ZIP')}
56 </a>
56 </a>
57 % endif
57 % endif
@@ -187,7 +187,7 b''
187 <div class="enabled pull-left" style="margin-right: 10px">
187 <div class="enabled pull-left" style="margin-right: 10px">
188
188
189 <div class="btn-group btn-group-actions">
189 <div class="btn-group btn-group-actions">
190 <a class="archive_link btn btn-small" data-ext=".zip" href="${h.route_path('repo_archivefile',repo_name=c.rhodecode_db_repo.repo_name, fname=c.rhodecode_db_repo.landing_ref_name+'.zip')}">
190 <a class="archive_link btn btn-small" data-ext=".zip" href="${h.route_path('repo_archivefile',repo_name=c.rhodecode_db_repo.repo_name, fname=c.rhodecode_db_repo.landing_ref_name+'.zip', _query={'with_hash': '1'})}">
191 <i class="icon-download"></i>
191 <i class="icon-download"></i>
192 ${c.rhodecode_db_repo.landing_ref_name}.zip
192 ${c.rhodecode_db_repo.landing_ref_name}.zip
193 ## replaced by some JS on select
193 ## replaced by some JS on select
@@ -202,8 +202,7 b''
202 % for a_type, content_type, extension in h.ARCHIVE_SPECS:
202 % for a_type, content_type, extension in h.ARCHIVE_SPECS:
203 % if extension not in ['.zip']:
203 % if extension not in ['.zip']:
204 <li>
204 <li>
205
205 <a class="archive_link" data-ext="${extension}" href="${h.route_path('repo_archivefile',repo_name=c.rhodecode_db_repo.repo_name, fname=c.rhodecode_db_repo.landing_ref_name+extension, _query={'with_hash': '1'})}">
206 <a class="archive_link" data-ext="${extension}" href="${h.route_path('repo_archivefile',repo_name=c.rhodecode_db_repo.repo_name, fname=c.rhodecode_db_repo.landing_ref_name+extension)}">
207 <i class="icon-download"></i>
206 <i class="icon-download"></i>
208 ${c.rhodecode_db_repo.landing_ref_name+extension}
207 ${c.rhodecode_db_repo.landing_ref_name+extension}
209 </a>
208 </a>
General Comments 0
You need to be logged in to leave comments. Login now