def git_checkout(path_to_git_repository, branch="master"): if not os.path.exists(os.path.join(path_to_git_repository, '.git')): raise ValueError("Invalid git repository") git_checkout_po = subprocess.Popen(split( '{git} -C {activity_path} checkout {branch}'.format( git=get_executable_path('git'), activity_path=path_to_git_repository, branch=branch)), stdout=subprocess.PIPE, stderr=subprocess.PIPE) ecode = git_checkout_po.wait(500) if ecode != 0: cprint( "WARN: checking out {} to {} failed.".format( path_to_git_repository, branch), "yellow") return 1 return 0
def git_checkout_latest_tag(path_to_git_repository): if not os.path.exists(os.path.join(path_to_git_repository, '.git')): raise ValueError("Invalid git repository") git_rev_list_tags_max_count = subprocess.Popen(split( '{git} -C {activity_path} rev-list --tags --max-count=1'.format( git=get_executable_path('git'), activity_path=path_to_git_repository)), stdout=subprocess.PIPE, stderr=subprocess.PIPE) e_code = git_rev_list_tags_max_count.wait(50) if e_code != 0: cprint( "FATAL: Could not process `rev-list --tags` for {}".format( path_to_git_repository), "red") return 1 git_commit_sha_of_tag, _ = \ decode_each(git_rev_list_tags_max_count.communicate()) git_describe_tags = subprocess.Popen(split( '{git} -C {activity_path} describe --tags {sha}'.format( git=get_executable_path('git'), activity_path=path_to_git_repository, sha=git_commit_sha_of_tag)), stdout=subprocess.PIPE, stderr=subprocess.PIPE) e_code = git_describe_tags.wait(50) if e_code != 0: cprint( "WARN: git describe --tags for {sha} failed for {git_repo}. " "Continuing to build from master...".format( sha=git_commit_sha_of_tag, git_repo=path_to_git_repository), "yellow") return 1 # checkout the tag tag, _err = decode_each(git_describe_tags.communicate()) git_checkout_po = subprocess.Popen(split( '{git} -C {activity_path} checkout {tag}'.format( git=get_executable_path('git'), activity_path=path_to_git_repository, tag=tag)), stdout=subprocess.PIPE, stderr=subprocess.PIPE) ecode = git_checkout_po.wait(500) if ecode != 0: cprint( "WARN: checking out {} to tag {} failed. Fallback to " "master.".format(path_to_git_repository, tag), "yellow") return 1 return 0
def do_generate_bundle(self, override_dist_xo=False, entrypoint_build_command=None, build_command_chdir=False, checkout_latest_tag=False): """ Generates a .xo file for the activities by spawning a subprocess Some additional pro level features ;) The script file supports python f-strings Pass the parameters as named {name}, {v} to get name and version appropriately Some important format specifiers {name} : Activity Name {v} : Activity version {activity_dir} : the path of the Activity, i.e ~/FractionBounce.Activity {icon_path}: the path of the icon path Make sure you add a cd (change directory) function within the shell / python script The script is run relative to path of execution. To change location each time before command execution, pass --build-chdir :return: Tuple (e_code, stdout, stderr) """ if self.is_xo: # I am already a xo. Why build me? duh return 0, '[xo] Already Built.', '' if override_dist_xo and not entrypoint_build_command: raise ValueError("entrypoint_build_command was not provided") if checkout_latest_tag and not self.is_xo: # checkout the latest tag on the activity build try: git_checkout_latest_tag(self.get_activity_dir()) except Exception as e: cprint( "WARN: git checkout to latest tag failed. E: {}".format(e), "yellow") current_path_ = os.getcwd() if entrypoint_build_command and isinstance(entrypoint_build_command, str): # read the shell / python script with open(entrypoint_build_command, 'r') as r: commands_to_pre_execute = r.read() # change dir, if necessary: if build_command_chdir: os.chdir(self.get_activity_dir()) # execute the commands, format the f-strings before execution exit_code = os.system( commands_to_pre_execute.format( name=self.get_name(), v=self.get_version(), activity_dir=self.get_activity_dir(), icon_path=self.get_icon_path())) # restore the current working directory in the case directory was # changed if build_command_chdir: os.chdir(current_path_) if override_dist_xo: return exit_code, '', '' python3_exe = get_executable_path( 'python3', False) or get_executable_path('python') python2_exe = get_executable_path( 'python2', False) or get_executable_path('python') # check the type of activity if self.get_activity_type() == 'python2': # in the case the software to be used is sugar-activity # use python2 in that case. python_exe = python2_exe else: # use the python3 version to build all the rest of the # types of the activities python_exe = python3_exe proc = subprocess.Popen(_s("{} setup.py dist_xo".format(python_exe)), cwd=self.get_activity_dir(), stderr=subprocess.PIPE, stdout=subprocess.PIPE) # wait for process to complete exit_code = wait_for_process_completion(proc) if exit_code: # process did not complete successfully return exit_code, '', '' # read the stdout and stderr out, err = proc.communicate() if not exit_code: dist_path = os.path.join(self.get_activity_dir(), 'dist') bundle = get_latest_bundle(dist_path) if bundle: self.set_bundle_path(bundle) if checkout_latest_tag and not self.is_xo: # restore the branch to master git_checkout(self.get_activity_dir()) return exit_code, out.decode(), err.decode()