@ShellMethod(key = "show restores", value = "List all restore instants")
  public String showRestores(
          @ShellOption(value = {"--limit"}, help = "Limit #rows to be displayed", defaultValue = "10") Integer limit,
          @ShellOption(value = {"--sortBy"}, help = "Sorting Field", defaultValue = "") final String sortByField,
          @ShellOption(value = {"--desc"}, help = "Ordering", defaultValue = "false") final boolean descending,
          @ShellOption(value = {"--headeronly"}, help = "Print Header Only",
                  defaultValue = "false") final boolean headerOnly,
          @ShellOption(value = {"--includeInflights"}, help = "Also list restores that are in flight",
                  defaultValue = "false") final boolean includeInflights) {

    HoodieActiveTimeline activeTimeline = HoodieCLI.getTableMetaClient().getActiveTimeline();
    List<HoodieInstant> restoreInstants = getRestoreInstants(activeTimeline, includeInflights);

    final List<Comparable[]> outputRows = new ArrayList<>();
    for (HoodieInstant restoreInstant : restoreInstants) {
      populateOutputFromRestoreInstant(restoreInstant, outputRows, activeTimeline);
    }

    TableHeader header = createResultHeader();
    return HoodiePrintHelper.print(header, new HashMap<>(), sortByField, descending, limit, headerOnly, outputRows);
  }
@Test
  public void testShowRestores() {
    Object result = shell.evaluate(() -> "show restores");
    assertTrue(ShellEvaluationResultUtil.isSuccess(result));

    // get restored instants
    HoodieActiveTimeline activeTimeline = HoodieCLI.getTableMetaClient().getActiveTimeline();
    Stream<HoodieInstant> restores = activeTimeline.getRestoreTimeline().filterCompletedInstants().getInstantsAsStream();

    List<Comparable[]> rows = new ArrayList<>();
    restores.sorted().forEach(instant -> {
      try {
        HoodieRestoreMetadata metadata = TimelineMetadataUtils
                .deserializeAvroMetadata(activeTimeline.getInstantDetails(instant).get(), HoodieRestoreMetadata.class);
        metadata.getInstantsToRollback().forEach(c -> {
          Comparable[] row = new Comparable[4];
          row[0] = metadata.getStartRestoreTime();
          row[1] = c;
          row[2] = metadata.getTimeTakenInMillis();
          row[3] = HoodieInstant.State.COMPLETED.toString();
          rows.add(row);
        });
      } catch (IOException e) {
        e.printStackTrace();
      }
    });

    TableHeader header = new TableHeader()
            .addTableHeaderField(HoodieTableHeaderFields.HEADER_INSTANT)
            .addTableHeaderField(HoodieTableHeaderFields.HEADER_RESTORE_INSTANT)
            .addTableHeaderField(HoodieTableHeaderFields.HEADER_TIME_TOKEN_MILLIS)
            .addTableHeaderField(HoodieTableHeaderFields.HEADER_RESTORE_STATE);
    String expected = HoodiePrintHelper.print(header, new HashMap<>(), "", false,
            -1, false, rows);
    expected = removeNonWordAndStripSpace(expected);
    String got = removeNonWordAndStripSpace(result.toString());
    assertEquals(expected, got);
  }