def pretty_packages(self, fields=None, max_width=0): if fields == None: fields = self.default_package_fields return rst_table(fields, [package.metadata for package in self.packages], max_width=max_width)
def rollback_menu(remote_repos=None, interactive=True, dry_run=False, term_width=0, show_all=False, num_entries=5, show_dates=False): """ Show a menu with possible rollback options and perform the appropriate action based on the user's input. """ # Create a list of metadata for the possible rollback dates so that we # can create an auto-generated user selection layout. Based on the # command-line options, we can limit the list of rollback points that # are shown. If the ensetuptools.cache doesn't exist, let the user know # why they can not do a rollback. cached_states = retrieve_states() if not cached_states: print ("A rollback can not be performed because there are " "no cached rollback points.") return if not show_all: cached_states = cached_states[:num_entries] metadata = [] local_time = time.localtime() for i, state in enumerate(cached_states): # Create a date display from the difference between the timestamp of # the rollback point and the current time. The difference we retrieve # is the time sine the epoch (i.e. January 1, 1970), so we make our # calculations from that. timestamp = state[0] time_tuple = time.strptime(timestamp, "%Y%m%d%H%M%S") date_display = date_display_diff(local_time, time_tuple) # If the user specified to display the full date/timestamp with the # rollback points, then tack it onto the simple display. if show_dates: date_display = "%s (%s)" % (date_display, time.strftime("%Y/%m/%d %H:%M:%S", time_tuple)) # Find the differences between two rollback points (i.e. packages # added, removed, or modified) and calculate a nice diff that can # be displayed in the table. # We need to stop calculating these diffs once we reach the last # item though because there are no entries after it. option_diff = "" if i < len(cached_states)-1: project_list_1 = cached_states[i][1] project_list_2 = cached_states[i+1][1] diff_list_1 = [project for project in project_list_1 if not project in project_list_2] diff_list_2 = [project for project in project_list_2 if not project in project_list_1] if len(diff_list_1) == 0 and len(diff_list_2) == 0: option_diff = " There are no changes between these points." else: added = [] modified = [] deactivated = [] for project in diff_list_1: (project_name_1, project_version_1) = parse_project_str(project) found = False for project2 in diff_list_2: (project_name_2, project_version_2) = parse_project_str(project2) if project_name_1 == project_name_2: found = True modified.append("%s-%s to %s" % ( project_name_1, project_version_2, project_version_1)) break if not found: added.append("%s-%s" % (project_name_1, project_version_1)) for project2 in diff_list_2: (project_name_2, project_version_2) = parse_project_str(project2) found = False for project in diff_list_1: (project_name_1, project_version_1) = parse_project_str(project) if project_name_2 == project_name_1: found = True break if not found: deactivated.append("%s-%s" % (project_name_2, project_version_2)) if len(added) > 0: option_diff += " [A] %s" % added[0] for add_str in added[1:]: option_diff += "\n\t %s" % add_str if len(modified) > 0 or len(deactivated) > 0: option_diff += "\n\t" if len(modified) > 0: option_diff += " [M] %s" % modified[0] for mod_str in modified[1:]: option_diff += "\n\t %s" % mod_str if len(deactivated) > 0: option_diff += "\n\t" if len(deactivated) > 0: option_diff += " [D] %s" % deactivated[0] for deac_str in deactivated[1:]: option_diff += "\n\t %s" % deac_str # Set the 'date' metadata according to the date display and # the differene between rollback points. metadata.append({"date": date_display + "\n\t" + option_diff}) # If a user selects to view more information about a specific rollback # point, keep prompting the user to choose a rollback point after # displaying that information. while True: selection = user_select(["date"], metadata, ("Select a restore point to rollback your " "environment to. For more information about a " "specific rollback point, type the option number " "followed by a question mark. Use '0' to cancel " "rollback: "), default="0", extra_char="?", max_width=term_width) if not selection.endswith("?"): break else: option = int(selection.split('?')[0])-1 state = cached_states[option] timestamp = state[0] time_tuple = time.strptime(timestamp, "%Y%m%d%H%M%S") date_display = time.strftime("%Y/%m/%d %H:%M:%S", time_tuple) print "Active Project State on %s:" % date_display state_data=[] project_list = state[1] for project in project_list: (project_name, project_version) = parse_project_str(project) state_data.append({"project_name": project_name, "version": project_version}) msg = rst_table(["project_name", "version"], state_data, sorted=False, max_width=term_width) msg += "\n\n" print msg # If the user selected option '0', then there's nothing to do. if selection == '0': return # Now that the user has selected a rollback point, perform the action # to rollback to that state. Once the rollback has been completed # successfully, let the user know. state_index = int(selection)-1 project_list = cached_states[state_index][1] rollback_state(project_list, remote_repos, interactive, dry_run, term_width) timestamp = cached_states[state_index][0] time_tuple = time.strptime(timestamp, "%Y%m%d%H%M%S") date_display = time.strftime("%Y/%m/%d %H:%M:%S", time_tuple) print "\nSystem successfully rolled back to state on: %s" % date_display