def add_backup(flags, bak_dir, name="unknown"): """ Adds a backup of the git repository. - bak_dir -- The destination directory. - name -- The name of the backup, replaces '_' with '-'. Returns the name of the created backup file. """ try: check_git_rep() # Make sure there are no '_' in the name. name.replace('_', '-') # Set the path to the new backup file. tar_name = "{0}_{1}{2}".format(name, strftime(_BAK_FILE_DATE_FORMAT), _BAK_FILE_EXT) tar_path = path.join(bak_dir, tar_name) # Make a safety backup of the current git repository. log(flags, "Creating backup file \'" + tar_path + "\'") if not flags[Flag.SAFEMODE]: mkdirs(flags, bak_dir) exec_cmd(["tar", "-czf", tar_path, "."]) return tar_name except Error as err: log(flags, "Could not add backup in \'" + bak_dir + "\'") raise OpError(err)
def log(self, flags): """ Log the error """ if self.msg is not None: # Print msg if set. log(flags, self.msg, TextType.ERR) if self.err is not None: # Print causing error if set. self.err.log(flags)
def log(self, flags): """ Log the error """ if self.opr is not None: log( flags, ("The git command '" + self.opr + "' failed\n" if self.opr is not None else "") + self.msg, TextType.ERR, ) else: log(flags, self.msg, TextType.ERR)
def restore_temp_commit(flags, restore_data): """ Restores the initial state before a temp commit was created. - restore_data -- The restore data returned from the 'create_temp_commit' function. """ try: # Restore branch. if restore_data[0] != get_branch(): log(flags, "Switching active branch to \'" + restore_data[0] + "\'") switch_branch(restore_data[0]) # Check if changes have been stashed (and temporary commit created). if restore_data[2] is not None: log(flags, "Resetting branch \'" + restore_data[0] + "\'to commit \'" + restore_data[1] + "\'") reset_branch(flags, restore_data[0], restore_data[1]) log(flags, "Restoring uncommitted changes from stash to " + "branch \'" + restore_data[0] + "\'") apply_stash(flags, restore_data[0], drop=True) except Error as err: raise OpError(err)
def create_temp_commit(flags): """ Commits any uncommitted changes on the current branch to a temporary commit. - branch -- The branch to tag. Returns the a tuple with the branch name, commit id and stash name, used to restore the initial state with the 'restore_temp_commit' function. If no changes can be committed the stash name is set to 'None'. """ try: # Save the current branch current_branch = get_branch() log(flags, "Saving current branch name \'{0}\' ".format(current_branch)) # Try to get the HEAD commit id of the current branch. head_commit = get_head_commit(current_branch) # Check for uncommitted changes. if not is_working_dir_clean(): log(flags, "Stashing uncommitted changes on branch \'{0}\'". format(current_branch)) # Save changes to tmp stash. stash_name = "gbpx<{0}>".format(head_commit) stash_changes(flags, stash_name) # Apply stash and create a temporary commit. log(flags, "Creating temporary commit on branch \'{0}\'". format(current_branch)) apply_stash(flags, current_branch, drop=False) commit_changes(flags, "Temp \'{0}\' commit.".format(current_branch)) else: stash_name = None log(flags, "Working directory clean, no commit needed") return current_branch, head_commit, stash_name except Error as err: raise OpError(err)
def verify_create_head_tag(flags, branch, tag_type, version_str=None): """ Verifies or creates a version tag for a branch HEAD. If tag needs to be created and no version is given, user will be prompted for version. - branch -- The branch to tag. - tag_type -- The tag type (<tag_type>/<version>). - version_str -- The version string to use. Returns the a tuple with version created or found and True if created otherwise False. (<version>, <created>) """ try: # Check that at least one head tag exists. if get_head_tags(branch, tag_type): log(flags, "The HEAD commit on branch \'" + branch + "\' is already tagged, skipping tagging") version_str = get_head_tag_version_str(branch, tag_type) return version_str, tag_type + "/" + version_str, False else: log(flags, "The HEAD commit on branch \'" + branch + "\' is not tagged correctly") if version_str is None: # Prompt user to tag the HEAD of release branch. raw_ver = prompt_user_input("Enter release version to tag", True) if raw_ver is not None: version_str = raw_ver else: raise OpError(msg="Tagging of HEAD commit on branch " + "\'" + branch + "\' aborted by user") # Tag using the given version string. tag = tag_type + "/" + version_str if not flags[Flag.SAFEMODE]: log(flags, "Tagging HEAD commit on branch \'" + branch + "\' as \'" + tag + "\'") tag_head(flags, branch, tag) return version_str, tag, True except Error as err: raise OpError(err)
def restore_backup(flags, bak_dir, num=None, name=None): """ Tries to restore repository to a saved backup. Will prompt the user for the requested restore point if num is not set. - bak_dir -- The backup storage directory. - num -- The index number of the restore point (latest first). """ try: check_git_rep() # If name is set just restore that file. if name is not None: bak_name = name else: # Find all previously backed up states. bak_files = get_files_with_extension(bak_dir, _BAK_FILE_EXT) if not bak_files: raise OpError("No backups exists in directory \'" + bak_dir + "\'") # Sort the bak_files according to date. bak_files.sort(key=lambda bak_f: [int(v) for v in bak_f.split('_')[1].split('.')[ 0].split('-')], reverse=True) # Set the max tab depth. max_tab_depth = max([1 + (len(s.split('_')[0]) // _TAB_WIDTH) for s in bak_files]) # Prompt user to select a state to restore. options = [] for f_name in bak_files: option = "\t" + f_name.split('_')[0] option += "\t" * (max_tab_depth - len(f_name.split('_')[0]) // _TAB_WIDTH) option += datetime.strptime( f_name.split('_')[1].split('.')[0], _BAK_FILE_DATE_FORMAT).strftime(_BAK_DISPLAY_DATE_FORMAT) options.append(option) # Check if prompt can be skipped. if num is not None: if num >= len(options) or num < 0: raise OpError("Invalid backup index \'" + num + "\' is outside [0-" + str(len(options) - 1) + "]") else: # Prompt. num = prompt_user_options("Select the backup to restore", options) if num is None: raise OpError(msg="Restore aborted by user") # Set the chosen backup name. bak_name = bak_files[num] # Restore backup. try: log(flags, "Restoring backup \'" + bak_name + "\'") clean_dir(flags, getcwd()) if not flags[Flag.SAFEMODE]: exec_cmd(["tar", "-xf", path.join(bak_dir, bak_name)]) except Error as err: log(flags, "Restore failed, the backup can be found in \'" + bak_dir + "\'", TextType.ERR) raise OpError(err) except GitError as err: log(flags, "Restore could not be completed") raise OpError(err)
def log(self, flags): """ Log the error """ log(flags, ("An error with file: " + self.file + "\n" if self.file is not None else "") + ( "On line: " + self.line + "\n" if self.line is not None else "") + self.msg, TextType.ERR)