def rebase_patches(without_git_rebase=True, directory=None): ### Ensure a clean/valid working environment ensure_clean_working_env(git_status=True, directory=directory) ### Make sure we need to actually call this # Get the current branch current_branch = get_current_branch(directory) if current_branch is None: error("Could not determine current branch.", exit=True) # Get the patches branch patches_branch = 'patches/' + current_branch # Get the current patches.conf config = get_patch_config(patches_branch, directory=directory) ### Execute the rebase if without_git_rebase: non_git_rebase(config['parent'], directory=directory) else: git_rebase(config['parent'], directory=directory) ### Update the patches information # Get the latest configs config = get_patch_config(patches_branch, directory) # Set the base to the current hash (before patches) current_branch_ = get_current_branch(directory) debug('Current branch: ' + current_branch_ or 'could not determine branch') config['base'] = get_commit_hash(current_branch_, directory) debug('New current commit hash after rebase: ' + config['base']) # Set the new upstream hash to the previous upstream hash config['previous'] = get_commit_hash(config['parent'], directory) debug('New parent commit hash after rebase: ' + config['previous']) # Clear the trimbase (it needs to be reapplied) config['trimbase'] = '' # Write the new configs set_patch_config(patches_branch, config, directory)
def post_rebase(self, destination): name = destination.split('/')[-1] # Retrieve the package package = self.packages[name] # Handle differently if this is a debian vs distro branch if destination in self.debian_branches: info("Placing debian template files into '{0}' branch.".format( destination)) # Then this is a debian branch # Place the raw template files self.place_template_files() else: # This is a distro specific debian branch # Determine the current package being generated distro = destination.split('/')[-2] # Create debians for each distro with inbranch(destination): data = self.generate_debian(package, distro) # Create the tag name for later self.tag_names[destination] = self.generate_tag_name(data) # Update the patch configs patches_branch = 'patches/' + destination config = get_patch_config(patches_branch) # Store it self.store_original_config(config, patches_branch) # Modify the base so import/export patch works current_branch = get_current_branch() if current_branch is None: error("Could not determine current branch.", exit=True) config['base'] = get_commit_hash(current_branch) # Set it set_patch_config(patches_branch, config)
def post_rebase(self, destination): name = destination.split('/')[-1] # Retrieve the package package = self.packages[name] # Handle differently if this is an rpm vs distro branch if destination in self.rpm_branches: info("Placing RPM template files into '{0}' branch." .format(destination)) # Then this is an rpm branch # Place the raw template files self.place_template_files() else: # This is a distro specific rpm branch # Determine the current package being generated distro = destination.split('/')[-2] # Create RPMs for each distro with inbranch(destination): data = self.generate_rpm(package, distro) # Create the tag name for later self.tag_names[destination] = self.generate_tag_name(data) # Update the patch configs patches_branch = 'patches/' + destination config = get_patch_config(patches_branch) # Store it self.store_original_config(config, patches_branch) # Modify the base so import/export patch works current_branch = get_current_branch() if current_branch is None: error("Could not determine current branch.", exit=True) config['base'] = get_commit_hash(current_branch) # Set it set_patch_config(patches_branch, config)
def post_rebase(self, destination): name = destination.split('/')[-1] # Retrieve the package package = self.packages[name] # Handle differently if this is an arch vs distro branch if destination in self.arch_branches: info("Placing Arch template files into '{0}' branch." .format(destination)) # Then this is an arch branch # Place the raw template files self.place_template_files() else: # This is a distro specific arch branch # Determine the current package being generated distro = destination.split('/')[-2] # Create Arch packages for each distro with inbranch(destination): # To fit Arch Linux philosophy a bit better, we move all the source files into a subdirectory. # Arch Linux doesn't support source distribution through a subdirectory; therefore we should ideally compress the sources or provide a URL. # At this point in the generator, it is tricky to get the release URL. Furthermore it wouldn't fit bloom's patch mechanism very well. # To work around, we copy the sources to the $srcdir at the beginning inside the prepare() function. temp_dir = mkdtemp(dir='.') for item in os.listdir("."): itemsrc = os.path.abspath(item) if os.path.basename(itemsrc) in ['.', '..', '.git', '.svn', 'arch',os.path.basename(temp_dir)]: continue itemdst = os.path.abspath(os.path.join(temp_dir,item)) execute_command('git mv ' + itemsrc + ' ' + itemdst) execute_command('git mv ' + temp_dir + ' ' + name) execute_command('git commit --amend --no-edit') # Then generate the PKGBUILD data = self.generate_arch(package, distro) # And finally move the PKGBUILD to the root directory of the package. for item in os.listdir("arch"): itemsrc = os.path.abspath(os.path.join("arch",item)) if os.path.basename(itemsrc) in ['.', '..', '.git', '.svn']: continue itemdst = os.path.abspath(item) execute_command('git mv ' + itemsrc + ' ' + itemdst) execute_command('git commit --amend --no-edit') # Create the tag name for later self.tag_names[destination] = self.generate_tag_name(data) # Update the patch configs patches_branch = 'patches/' + destination config = get_patch_config(patches_branch) # Store it self.store_original_config(config, patches_branch) # Modify the base so import/export patch works current_branch = get_current_branch() if current_branch is None: error("Could not determine current branch.", exit=True) config['base'] = get_commit_hash(current_branch) # Set it set_patch_config(patches_branch, config)
def pre_rebase(self, destination): # Get the stored configs is any patches_branch = 'patches/' + destination config = self.load_original_config(patches_branch) if config is not None: curr_config = get_patch_config(patches_branch) if curr_config['parent'] == config['parent']: set_patch_config(patches_branch, config)
def post_rebase(self, destination): name = destination.split('/')[-1] # Retrieve the stackage stackage, kind = self.packages[name] # Handle differently if this is a debian vs distro branch if destination in self.debian_branches: info("Placing debian template files into '{0}' branch.".format(destination)) # Check for valid CMakeLists.txt if a metapackage if kind == 'package' and is_metapackage(stackage): check_metapackage_for_valid_cmake(name) # Then this is a debian branch # Place the raw template files self.place_tempalte_files() else: # Check for valid CMakeLists.txt if a metapackage if kind == 'package' and is_metapackage(stackage): check_metapackage_for_valid_cmake(name) # This is a distro specific debian branch # Determine the current package being generated distro = destination.split('/')[-2] ### Start debian generation # Get time of day from dateutil import tz stamp = datetime.datetime.now(tz.tzlocal()) # Convert stackage to debian data data = self.convert_stackage_to_debian_data(stackage, kind) # Get apt_installer from rosdep from rosdep2.catkin_support import get_installer self.apt_installer = get_installer(APT_INSTALLER) # Create debians for each distro with inbranch(destination): self.generate_debian(data, stamp, distro) # Create the tag name for later self.tag_names[destination] = self.generate_tag_name(data) # Update the patch configs patches_branch = 'patches/' + destination config = get_patch_config(patches_branch) # Store it self.store_original_config(config, patches_branch) # Modify the base so import/export patch works current_branch = get_current_branch() if current_branch is None: error("Could not determine current branch.", exit=True) config['base'] = get_commit_hash(current_branch) # Set it set_patch_config(patches_branch, config)
def trim(sub_dir=None, force=False, undo=False, directory=None): # Get the current branch current_branch = get_current_branch(directory) # Ensure the current branch is valid if current_branch is None: error("Could not determine current branch, are you in a git repo?", exit=True) # Construct the patches branch patches_branch = 'patches/' + current_branch try: # See if the patches branch exists if branch_exists(patches_branch, False, directory=directory): if not branch_exists(patches_branch, True, directory=directory): track_branches(patches_branch, directory) else: error("No patches branch (" + patches_branch + ") found, cannot " "perform trim.", exit=True) # Get the parent branch from the patches branch config = get_patch_config(patches_branch, directory=directory) if config is None: error("Could not retrieve patches info.", exit=True) # If sub_dir is set, try to set it new_config = _set_trim_sub_dir(sub_dir, force, config, directory) if new_config is None: sys.exit('Could not perform trim') # Perform trime or undo if undo: new_config = _undo(new_config, directory) if new_config is None: return -1 # Indicates that nothing was done else: new_config = _trim(new_config, force, directory) if new_config is None: sys.exit('Could not perform trim') # Commit the new config set_patch_config(patches_branch, new_config, directory) finally: if current_branch: checkout(current_branch, directory=directory)
def remove_patches(directory=None): # Get the current branch current_branch = get_current_branch(directory) if current_branch is None: error("Could not determine current branch.", exit=True) # Ensure the current branch is valid if current_branch is None: error("Could not determine current branch, are you in a git repo?", exit=True) # Construct the patches branch patches_branch = 'patches/' + current_branch try: # See if the patches branch exists if branch_exists(patches_branch, False, directory=directory): if not branch_exists(patches_branch, True, directory=directory): track_branches(patches_branch, directory) else: error("No patches branch (" + patches_branch + ") found, cannot " "remove patches.", exit=True) # Get the parent branch from the patches branch config = get_patch_config(patches_branch, directory=directory) parent, spec = config['parent'], config['base'] if None in [parent, spec]: error("Could not retrieve patches info.", exit=True) debug("Removing patches from " + current_branch + " back to base " "commit " + spec) # Reset this branch using git revert --no-edit spec current_commit = get_commit_hash(current_branch, directory) command_spec = spec + '..' + current_commit execute_command('git revert --no-edit -Xtheirs ' + command_spec, cwd=directory) # Update the base config['base'] = get_commit_hash(current_branch, directory) set_patch_config(patches_branch, config, directory=directory) finally: if current_branch: checkout(current_branch, directory=directory)
def remove_patches(directory=None): # Get the current branch current_branch = get_current_branch(directory) if current_branch is None: error("Could not determine current branch.", exit=True) # Ensure the current branch is valid if current_branch is None: error("Could not determine current branch, are you in a git repo?", exit=True) # Construct the patches branch patches_branch = 'patches/' + current_branch try: # See if the patches branch exists if branch_exists(patches_branch, False, directory=directory): if not branch_exists(patches_branch, True, directory=directory): track_branches(patches_branch, directory) else: error("No patches branch (" + patches_branch + ") found, cannot " "remove patches.", exit=True) # Get the parent branch from the patches branch config = get_patch_config(patches_branch, directory=directory) parent, spec = config['parent'], config['base'] if None in [parent, spec]: error("Could not retrieve patches info.", exit=True) debug("Removing patches from " + current_branch + " back to base " "commit " + spec) # Reset this branch using git revert --no-edit spec current_commit = get_commit_hash(current_branch, directory) command_spec = spec + '..' + current_commit execute_command( 'git revert --no-edit -Xtheirs ' + command_spec, cwd=directory ) # Update the base config['base'] = get_commit_hash(current_branch, directory) set_patch_config(patches_branch, config, directory=directory) finally: if current_branch: checkout(current_branch, directory=directory)
ls_remote = subprocess.check_output(['git', 'ls-remote', '--heads', 'oldorigin', f'*{args.source}*'], universal_newlines=True) for line in ls_remote.split('\n'): if line == '': continue obj, ref = line.split('\t') ref = ref[11:] # strip 'refs/heads/' newref = ref.replace(args.source, args.dest) subprocess.check_call(['git', 'branch', newref, obj]) if newref.startswith('patches/'): # Update parent in patch configs. Without this update the # patches will be rebased out when git-bloom-release is # called because the configured parent won't match the # expected source branch. config = get_patch_config(newref) config['parent'] = config['parent'].replace(args.source, args.dest) set_patch_config(newref, config) write_tracks_file(tracks, f'Copy {args.source} track to {args.dest} with migrate-rosdistro.py.') else: dest_track = tracks['tracks'][args.dest] # Configure next release to re-release previous version into the # destination. A version value of :{ask} will fail due to # interactivity and :{auto} may result in a previously unreleased tag # on the development branch being released for the first time. if dest_track['version'] in [':{ask}', ':{auto}']: # Override the version for this release to guarantee the same version is released. dest_track['version_saved'] = dest_track['version'] dest_track['version'] = dest_track['last_version'] write_tracks_file(tracks, f'Update {args.dest} track to release exactly last-released version.') if dest_track['release_tag'] == ':{ask}' and 'last_release' in dest_track:
def execute_branch(src, dst, interactive, directory=None): """ Changes to the destination branch, creates branch and patches/branch if they do not exist. If the dst branch does not exist yet, then it is created by branching the current working branch or the specified SRC_BRANCH. If the patches/dst branch branch does not exist yet then it is created. If the branches are created successful, then the working branch will be set to the dst branch, otherwise the working branch will remain unchanged. :param src: source branch from which to copy :param dst: destination branch :param interactive: if True actions are summarized before committing :param directory: directory in which to preform this action :raises: subprocess.CalledProcessError if any git calls fail """ # Determine if the srouce branch exists if src is None: error("No source specified and/or not a branch currently", exit=True) if branch_exists(src, local_only=False, directory=directory): if not branch_exists(src, local_only=True, directory=directory): debug("Tracking source branch: {0}".format(src)) track_branches(src, directory) elif tag_exists(src): pass else: error("Specified source branch does not exist: {0}".format(src), exit=True) # Determine if the destination branch needs to be created create_dst_branch = False if branch_exists(dst, local_only=False, directory=directory): if not branch_exists(dst, local_only=True, directory=directory): debug("Tracking destination branch: {0}".format(dst)) track_branches(dst, directory) else: create_dst_branch = True # Determine if the destination patches branch needs to be created create_dst_patches_branch = False dst_patches = "patches/" + dst if branch_exists(dst_patches, False, directory=directory): if not branch_exists(dst_patches, True, directory=directory): track_branches(dst_patches, directory) else: create_dst_patches_branch = True # Summarize if interactive: info("Summary of changes:") if create_dst_branch: info( " " * 22 + "- The specified destination branch, " + ansi("boldon") + dst + ansi("reset") + ", does not exist; it will be created from the source " "branch " + ansi("boldon") + src + ansi("reset") ) if create_dst_patches_branch: info( " " * 22 + "- The destination patches branch, " + ansi("boldon") + dst_patches + ansi("reset") + ", does not exist; it will be created" ) info(" " * 22 + "- The working branch will be set to " + ansi("boldon") + dst + ansi("reset")) if not maybe_continue(): error("Answered no to continue, aborting.", exit=True) # Make changes to the layout current_branch = get_current_branch(directory) try: # Change to the src branch checkout(src, directory=directory) # Create the dst branch if needed if create_dst_branch: create_branch(dst, changeto=True, directory=directory) else: checkout(dst, directory=directory) # Create the dst patches branch if needed if create_dst_patches_branch: create_branch(dst_patches, orphaned=True, directory=directory) # Create the starting config data if it does not exist patches_ls = ls_tree(dst_patches, directory=directory) if "patches.conf" not in patches_ls: # Patches config not setup, set it up config = { "parent": src, "previous": "", "base": get_commit_hash(dst, directory=directory), "trim": "", "trimbase": "", } set_patch_config(dst_patches, config, directory=directory) else: config = get_patch_config(dst_patches, directory=directory) if config["parent"] != src: warning("Updated parent to '{0}' from '{1}'".format(src, config["parent"])) config["parent"] = src config["base"] = get_commit_hash(dst, directory=directory) set_patch_config(dst_patches, config, directory=directory) # Command successful, do not switch back to previous branch current_branch = None finally: if current_branch is not None: checkout(current_branch, directory=directory)
def execute_branch(src, dst, interactive, directory=None): """ Changes to the destination branch, creates branch and patches/branch if they do not exist. If the dst branch does not exist yet, then it is created by branching the current working branch or the specified SRC_BRANCH. If the patches/dst branch branch does not exist yet then it is created. If the branches are created successful, then the working branch will be set to the dst branch, otherwise the working branch will remain unchanged. :param src: source branch from which to copy :param dst: destination branch :param interactive: if True actions are summarized before committing :param directory: directory in which to preform this action :raises: subprocess.CalledProcessError if any git calls fail """ # Determine if the srouce branch exists if src is None: error("No source specified and/or not a branch currently", exit=True) if branch_exists(src, local_only=False, directory=directory): if not branch_exists(src, local_only=True, directory=directory): debug("Tracking source branch: {0}".format(src)) track_branches(src, directory) elif tag_exists(src): pass else: error("Specified source branch does not exist: {0}".format(src), exit=True) # Determine if the destination branch needs to be created create_dst_branch = False if branch_exists(dst, local_only=False, directory=directory): if not branch_exists(dst, local_only=True, directory=directory): debug("Tracking destination branch: {0}".format(dst)) track_branches(dst, directory) else: create_dst_branch = True # Determine if the destination patches branch needs to be created create_dst_patches_branch = False dst_patches = 'patches/' + dst if branch_exists(dst_patches, False, directory=directory): if not branch_exists(dst_patches, True, directory=directory): track_branches(dst_patches, directory) else: create_dst_patches_branch = True # Summarize if interactive: info("Summary of changes:") if create_dst_branch: info(" " * 22 + "- The specified destination branch, " + ansi('boldon') + dst + ansi('reset') + ", does not exist; it will be created from the source " "branch " + ansi('boldon') + src + ansi('reset')) if create_dst_patches_branch: info(" " * 22 + "- The destination patches branch, " + ansi('boldon') + dst_patches + ansi('reset') + ", does not exist; it will be created") info(" " * 22 + "- The working branch will be set to " + ansi('boldon') + dst + ansi('reset')) if not maybe_continue(): error("Answered no to continue, aborting.", exit=True) # Make changes to the layout current_branch = get_current_branch(directory) try: # Change to the src branch checkout(src, directory=directory) # Create the dst branch if needed if create_dst_branch: create_branch(dst, changeto=True, directory=directory) else: checkout(dst, directory=directory) # Create the dst patches branch if needed if create_dst_patches_branch: create_branch(dst_patches, orphaned=True, directory=directory) # Create the starting config data if it does not exist patches_ls = ls_tree(dst_patches, directory=directory) if 'patches.conf' not in patches_ls: # Patches config not setup, set it up config = { 'parent': src, 'previous': '', 'base': get_commit_hash(dst, directory=directory), 'trim': '', 'trimbase': '' } set_patch_config(dst_patches, config, directory=directory) else: config = get_patch_config(dst_patches, directory=directory) if config['parent'] != src: warning("Updated parent to '{0}' from '{1}'".format( src, config['parent'])) config['parent'] = src config['base'] = get_commit_hash(dst, directory=directory) set_patch_config(dst_patches, config, directory=directory) # Command successful, do not switch back to previous branch current_branch = None finally: if current_branch is not None: checkout(current_branch, directory=directory)