| 
1
 | 
     1 #!/usr/bin/python
 | 
| 
 | 
     2 ## ********************************* GIT ARCHIVE *******************************
 | 
| 
 | 
     3 ##
 | 
| 
 | 
     4 
 | 
| 
 | 
     5 import os, sys
 | 
| 
 | 
     6 import vdb_common
 | 
| 
 | 
     7 import vdb_data_stores
 | 
| 
 | 
     8 import subprocess
 | 
| 
 | 
     9 import datetime
 | 
| 
 | 
    10 
 | 
| 
 | 
    11 class VDBGitDataStore(vdb_data_stores.VDBDataStore):
 | 
| 
 | 
    12 
 | 
| 
 | 
    13 	def __init__(self, retrieval_obj, spec_file_id):
 | 
| 
 | 
    14 		"""
 | 
| 
 | 
    15 		Archive is expected to be in "master/" subfolder of data_store_path on server.  
 | 
| 
 | 
    16 		"""
 | 
| 
 | 
    17 		super(VDBGitDataStore, self).__init__(retrieval_obj, spec_file_id)
 | 
| 
 | 
    18 		self.command = 'git'
 | 
| 
 | 
    19 		gitPath = self.data_store_path + 'master/'
 | 
| 
 | 
    20 		if not os.path.isdir(os.path.join(gitPath,'.git') ):
 | 
| 
 | 
    21 			print "Error: Unable to locate git archive file: " + gitPath
 | 
| 
 | 
    22 			sys.exit(1) 
 | 
| 
 | 
    23 		
 | 
| 
 | 
    24 		command = [self.command, '--git-dir=' + gitPath + '.git', '--work-tree=' + gitPath, 'for-each-ref','--sort=-*committerdate', "--format=%(*committerdate:raw) %(refname)"]
 | 
| 
 | 
    25 		#	to list just 1 id: command.append('refs/tags/' + version_id)
 | 
| 
 | 
    26 		# git --git-dir=/.../NCBI_16S/master/.git --work-tree=/.../NCBI_16S/master/ tag
 | 
| 
 | 
    27 		items, error = subprocess.Popen(command,stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
 | 
| 
 | 
    28 		items = items.split("\n") #Loop through list of tags
 | 
| 
 | 
    29 		versions = []
 | 
| 
 | 
    30 		for ptr, item in enumerate(items):
 | 
| 
 | 
    31 
 | 
| 
 | 
    32 			# Ignore master branch name; time is included as separate field in all other cases
 | 
| 
 | 
    33 			if item.strip().find(" ") >0: 
 | 
| 
 | 
    34 				(vtime, voffset, name) = item.split(" ")
 | 
| 
 | 
    35 				created = vdb_common.get_unix_time(vtime, voffset)
 | 
| 
 | 
    36 				item_name = name[10:] #strip 'refs/tags/' part off
 | 
| 
 | 
    37 				versions.append({'name':item_name, 'id':item_name, 'created': created})
 | 
| 
 | 
    38 		
 | 
| 
 | 
    39 		self.versions = versions
 | 
| 
 | 
    40 
 | 
| 
 | 
    41 	
 | 
| 
 | 
    42 	def get_version(self, version_name):
 | 
| 
 | 
    43 		"""
 | 
| 
 | 
    44 		Returns server folder path to version folder containing git files for a given version_id (git tag)
 | 
| 
 | 
    45 		
 | 
| 
 | 
    46 		FUTURE: TO AVOID USE CONFLICTS FOR VERSION RETRIEVAL, GIT CLONE INTO TEMP FOLDER 
 | 
| 
 | 
    47 		with -s / --shared and -n / --no-checkout (to avoid head build) THEN CHECKOUT version
 | 
| 
 | 
    48 		...
 | 
| 
 | 
    49 		REMOVE CLONE GIT REPO
 | 
| 
 | 
    50 
 | 
| 
 | 
    51 		@param galaxy_instance object A Bioblend galaxy instance
 | 
| 
 | 
    52 		@param library_id string Identifier for a galaxy data library
 | 
| 
 | 
    53 		@param library_label_path string Full hierarchic label of a library file or folder, PARENT of version id folder.
 | 
| 
 | 
    54 
 | 
| 
 | 
    55 		@param base_folder_id string a library folder id under which version files should exist	
 | 
| 
 | 
    56 		@param version_id alphaneumeric string (git tag)
 | 
| 
 | 
    57 		
 | 
| 
 | 
    58 		"""
 | 
| 
 | 
    59 		version = self.get_metadata_version(version_name)
 | 
| 
 | 
    60 		
 | 
| 
 | 
    61 		if not version:
 | 
| 
 | 
    62 			print 'Error: Galaxy was not able to find the given version id in the %s data store.' % self.version_path
 | 
| 
 | 
    63 			sys.exit( 1 )
 | 
| 
 | 
    64 			
 | 
| 
 | 
    65 		version_name = version['name']
 | 
| 
 | 
    66 		self.version_path = os.path.join(self.data_store_path, version_name)
 | 
| 
 | 
    67 		self.version_label = vdb_common.lightDate(version['created']) + '_v' + version_name
 | 
| 
 | 
    68 		self.library_version_path = os.path.join(self.library_label_path, self.version_label)
 | 
| 
 | 
    69 
 | 
| 
 | 
    70 		# If Data Library Versioned Data folder doesn't exist for this version, then create it
 | 
| 
 | 
    71 		if not os.path.exists(self.version_path):
 | 
| 
 | 
    72 			try:		
 | 
| 
 | 
    73 				os.mkdir(self.version_path)
 | 
| 
 | 
    74 			except:
 | 
| 
 | 
    75 				print 'Error: Galaxy was not able to create data store folder "%s".  Check permissions?' % self.version_path
 | 
| 
 | 
    76 				sys.exit( 1 )
 | 
| 
 | 
    77 
 | 
| 
 | 
    78 		if os.listdir(self.version_path) == []: 	
 | 
| 
 | 
    79 			
 | 
| 
 | 
    80 			git_path = self.data_store_path + 'master/'
 | 
| 
 | 
    81 			# RETRIEVE LIST OF FILES FOR GIVEN GIT TAG (using "ls-tree".  
 | 
| 
 | 
    82 			# It can happen independently of git checkout)
 | 
| 
 | 
    83 
 | 
| 
 | 
    84 			command = [self.command,  '--git-dir=%s/.git' % git_path, 'ls-tree','--name-only','-r', version_name]
 | 
| 
 | 
    85 			items, error = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
 | 
| 
 | 
    86 			git_files = items.split('\n')
 | 
| 
 | 
    87 		
 | 
| 
 | 
    88 			# PERFORM GIT CHECKOUT 
 | 
| 
 | 
    89 			command = [self.command, '--git-dir=%s/.git' % git_path, '--work-tree=%s' % git_path, 'checkout', version_name]
 | 
| 
 | 
    90 			results, error = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()		
 | 
| 
 | 
    91 		
 | 
| 
 | 
    92 			vdb_common.move_files(git_path, self.version_path, git_files)
 | 
| 
 | 
    93 
 | 
| 
 | 
    94 
 | 
| 
 | 
    95 
 | 
| 
 | 
    96 	def get_metadata_version(self, version_name=''):
 | 
| 
 | 
    97 		if version_name == '':
 | 
| 
 | 
    98 			return self.versions[0]
 | 
| 
 | 
    99 
 | 
| 
 | 
   100 		for version in self.versions:
 | 
| 
 | 
   101 			if str(version['name']) == version_name:
 | 
| 
 | 
   102 				return version
 | 
| 
 | 
   103 							
 | 
| 
 | 
   104 		return False
 | 
| 
 | 
   105 		
 | 
| 
 | 
   106 		
 |