def update_references(commit_id: str, wit_dir: Optional[str] = None, checkout: bool = False) -> None: """Update the reference file in `wit_dir`.""" if wit_dir is None: try: wit_dir = utilities.get_wit_dir() except FileNotFoundError as err: print(err) return reference_path = os.path.join(wit_dir, 'references.txt') active_branch = utilities.get_active_branch(wit_dir) if active_branch: active_branch_id = utilities.get_parent_id(wit_dir)[active_branch] if not checkout and active_branch_id == utilities.get_parent_id( wit_dir)['HEAD']: active_branch_id = commit_id with open(reference_path, 'r') as file_handler: reference = file_handler.readlines() text = '' for line in reference: branch_name, branch_id = line.rstrip().split('=') if branch_name == 'HEAD': branch_id = commit_id elif branch_name == active_branch: branch_id = active_branch_id text += f'{branch_name}={branch_id}\n' with open(reference_path, 'w') as file_handler: file_handler.write(text.rstrip())
def get_adjacency(wit_dir: Optional[str] = None, branch_id: Optional[str] = None, all_commits: bool = False) -> Dict[str, List[str]]: """Return an 'adjacency list' dictionary of commit inheritance to draw a graph from.""" if wit_dir is None: wit_dir = utilities.get_wit_dir() try: if branch_id: head_id = branch_id else: head_id = utilities.get_parent_id(wit_dir)['HEAD'] except KeyError: head_id = 'None' adjacency: Dict[str, List[str]] = {} if head_id != 'None': adjacency[head_id] = utilities.get_parent_id( wit_dir, commit_id=head_id)['parent'].split(', ') update_adjacency(adjacency, wit_dir) if all_commits: for commit_id in os.listdir(os.path.join(wit_dir, 'images')): if '.txt' not in commit_id and commit_id not in adjacency: adjacency[commit_id] = utilities.get_parent_id( wit_dir, commit_id=commit_id)['parent'].split(', ') return adjacency
def add_annotation(G: Any, wit_dir: str) -> Any: """Add labels with branch names to nodes in `G`""" pos = nx.circular_layout(G) pos_len = len(pos) if pos_len == 1: label_dif = LABEL_DIF_2 double_x = DOUBLE_X_2 double_y = DOUBLE_Y_2 else: label_dif = LABEL_DIF + pos_len / DIVISOR double_x = DOUBLE_X + pos_len / DIVISOR double_y = DOUBLE_Y branches = utilities.get_parent_id(wit_dir) all_ids: List[str] = [] for branch_name in branches: branch_id = branches[branch_name] if branch_id in pos: branch_pos = pos[branch_id] branch_label = [ branch_pos[0] - label_dif, branch_pos[1] - label_dif / BRANCH_DIVISOR ] if branch_id in all_ids: count = all_ids.count(branch_id) branch_label = [ branch_label[0] - double_x, branch_label[1] + double_y * count ] plt.annotate(branch_name, xy=branch_pos, xytext=branch_label, arrowprops=ARROW_PROPS) all_ids.append(branch_id) return pos
def create_metadata_file(commit_id: str, *message: str, merged_branch_id: Optional[str] = None, wit_dir: Optional[str] = None) -> None: """Create a metadata file for the current image.""" if wit_dir is None: try: wit_dir = utilities.get_wit_dir() except FileNotFoundError as err: print(err) return images_dir = os.path.join(wit_dir, 'images') metadata_path = os.path.join(images_dir, f'{commit_id}.txt') try: parent = utilities.get_parent_id(wit_dir)['HEAD'] if merged_branch_id: parent += f', {merged_branch_id}' except KeyError: parent = 'None' cur_time = time.strftime('%a %b %d %H:%M:%S %Y %z', time.gmtime()) printable = f'parent={parent}\ndate={cur_time}' if message: to_print = ' '.join(message) printable += f'\nmessage={to_print}' with open(metadata_path, 'x') as metadata: metadata.write(printable)
def update_adjacency(adjacency: Dict[str, List[str]], wit_dir: str) -> None: """Update adjacency list in `adjacency` based on its values.""" length = len(adjacency) temp = list(adjacency.values()) for commits in temp: for commit_id in commits: if commit_id not in adjacency and commit_id != 'None': adjacency[commit_id] = utilities.get_parent_id( wit_dir, commit_id=commit_id)['parent'].split(', ') if len(adjacency) != length: update_adjacency(adjacency, wit_dir)
def checkout(commit_id: str) -> None: """Rollback to a previous image.""" try: wit_dir_parent = utilities.get_wit_dir_parent() except FileNotFoundError as err: print(err) return wit_dir = os.path.join(wit_dir_parent, '.wit') branches = utilities.get_parent_id(wit_dir) if commit_id not in branches and commit_id not in os.listdir( os.path.join(wit_dir, 'images')): print('Invalid commit id. Unable to perform checkout.') return changes, unstaged, _, _ = status(no_print=True) if changes or unstaged: print( 'Unable to perform checkout. There are changes not yet committed.') return if commit_id in branches: branch_name = commit_id commit_id = branches[commit_id] elif commit_id in branches.values(): for key, value in branches.items(): if value == commit_id: branch_name = key else: branch_name = '' utilities.update_activated(branch_name, wit_dir) for file in status_funcs.get_all_files( os.path.join(wit_dir, 'images', commit_id)): og_path = utilities.get_original_name(file) staging_area = utilities.get_new_path(og_path, wit_dir_parent, additions=['staging_area']) for path in (og_path, staging_area): if os.path.exists(path): try: os.remove(path) except PermissionError: shutil.rmtree(path) try: shutil.copy2(file, path) except PermissionError: shutil.copytree(file, path) commit_funcs.update_references(commit_id, wit_dir, checkout=True) print(f'Reverted to {commit_id}')
def branch(branch_name: str) -> None: """Label the current commit id as `branch_name`, and define it as the acctivated branch.""" try: wit_dir = utilities.get_wit_dir() except FileNotFoundError as err: print(err) return branches = utilities.get_parent_id(wit_dir) head_id = branches['HEAD'] reference = os.path.join(wit_dir, 'references.txt') if branch_name not in branches: with open(reference, 'a') as file_handler: file_handler.write(f'\n{branch_name}={head_id}') print(f'Branch \'{branch_name}\' created.') else: print(f'A branch named \'{branch_name}\' already exists.')
def status( no_print: bool = False ) -> Tuple[List[str], List[str], List[str], List[str]]: """Print commitment status of files.""" parent_dir = utilities.get_wit_dir_parent() wit_dir = os.path.join(parent_dir, '.wit') staging_area = os.path.join(wit_dir, 'staging_area') try: head_id = utilities.get_parent_id(wit_dir)['HEAD'] except KeyError: head_id = '' changes = [ os.path.join(parent_dir, path) for path in os.listdir(staging_area) ] removed = [] else: last_image = os.path.join(wit_dir, 'images', head_id) changes = list( status_funcs.get_nonexistent_files(staging_area, last_image)) changes.extend( list(status_funcs.get_changed_files(staging_area, last_image))) removed = list( status_funcs.get_nonexistent_files(last_image, parent_dir)) unstaged = list(status_funcs.get_changed_files(parent_dir, staging_area)) untracked = list( status_funcs.get_nonexistent_files(parent_dir, staging_area)) if not no_print: printable = '' if head_id: printable += f'Current commit id: {head_id}' active_branch = utilities.get_active_branch(wit_dir) if active_branch: printable += f'\nActive branch: {active_branch}' else: printable += 'No images currently exist.' printable += (f'\n\nChanges to be committed:\n{changes}' f'\n\nUnstaged changes:\n{unstaged}' f'\n\nUntracked files:\n{untracked}' f'\n\nRemoved files:\n{removed}') print(printable) return changes, unstaged, untracked, removed