code: func (h *DaemonSetHistoryViewer) ViewHistory(namespace, name string, revision int64) (string, error) {
  	ds, history, err := daemonSetHistory(h.c.AppsV1(), namespace, name)
  	if err != nil {
  		return "", err
  	}
  	historyInfo := make(map[int64]*appsv1.ControllerRevision)
  	for _, history := range history {
  		// TODO: for now we assume revisions don't overlap, we may need to handle it
  		historyInfo[history.Revision] = history
  	}
  	if len(historyInfo) == 0 {
  		return "No rollout history found.", nil
  	}
  
  	// Print details of a specific revision
  	if revision > 0 {
  		history, ok := historyInfo[revision]
  		if !ok {
  			return "", fmt.Errorf("unable to find the specified revision")
  		}
  		dsOfHistory, err := applyDaemonSetHistory(ds, history)
  		if err != nil {
  			return "", fmt.Errorf("unable to parse history %s", history.Name)
  		}
  		return printTemplate(&dsOfHistory.Spec.Template)
  	}
  
  	// Print an overview of all Revisions
  	// Sort the revisionToChangeCause map by revision
  	revisions := make([]int64, 0, len(historyInfo))
  	for r := range historyInfo {
  		revisions = append(revisions, r)
  	}
  	sliceutil.SortInts64(revisions)
  
  	return tabbedString(func(out io.Writer) error {
  		fmt.Fprintf(out, "REVISION\tCHANGE-CAUSE\n")
  		for _, r := range revisions {
  			// Find the change-cause of revision r
  			changeCause := historyInfo[r].Annotations[ChangeCauseAnnotation]
  			if len(changeCause) == 0 {
  				changeCause = "<none>"
  			}
  			fmt.Fprintf(out, "%d\t%s\n", r, changeCause)
  		}
  		return nil
  	})
  }
docs: // ViewHistory returns a revision-to-history map as the revision history of a deployment
  // TODO: this should be a describer