Login
f-zip.c at [09094cea7b]
Login

File f-apps/f-zip.c artifact 33fc02d273 part of check-in 09094cea7b


/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 
/* vim: set ts=2 et sw=2 tw=80: */
/*
  Copyright 2013-2021 The Libfossil Authors, see LICENSES/BSD-2-Clause.txt

  SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  SPDX-FileCopyrightText: 2021 The Libfossil Authors
  SPDX-ArtifactOfProjectName: Libfossil
  SPDX-FileType: Code

  Heavily indebted to the Fossil SCM project (https://fossil-scm.org).
*/
/*
  This file creates ZIP files from fossil repository content.
*/

#include "fossil-scm/fossil-cli.h" /* Fossil App mini-framework */

static int vbose = 0;

static int fsl_card_F_visitor_progress(fsl_card_F const * fc,
                                  void * state){
  ++(*((int*)state));
  if(vbose>1){
    f_out("Adding: %.12s %s\n", fc->uuid, fc->name);
  }
  return 0;
}

int main(int argc, char const * const * argv ){
  int rc = 0;
  const char * sym = NULL;
  const char * fileName = NULL;
  const char * rootDir = NULL;
  fsl_cx * f;
  fsl_db * db;
  bool noRoot = false;
  fsl_uuid_str uuid = NULL;
  int fileCounter = 0;
  bool fQuiet = false;

  fcli_cliflag FCliFlags[] = {
    FCLI_FLAG_BOOL("q","quiet",&fQuiet,
                "Suppress non-error output unless --verbose is used."),
    FCLI_FLAG("r","root","dir-name",&rootDir,
              "Use the given name for the zip file's top-most "
              "directory. The default is based on the project's name "
              "and exported version."),
    fcli_cliflag_empty_m
  };
  fcli.cliFlags = FCliFlags;
  fcli_help_info FCliHelp = {
    "Creates ZIP files from fossil repository checkins.",
    "CHECKIN_VERSION OUTPUT_FILE",
    NULL
  };
  fcli.appHelp = &FCliHelp;

  rc = fcli_setup(argc, argv);
  if(rc) goto end;
  noRoot = fcli_flag("no-root",NULL) /* undocumented flag, for testing only.*/;
  vbose = fcli_is_verbose();
  f = fcli_cx();
  db = fsl_needs_repo(f);
  if(!db){
    rc = FSL_RC_NOT_A_REPO;
    goto end;
  }
  if(!vbose){
    vbose = fQuiet ? 0 : 1;
  }
  if(fcli_has_unused_flags(0)) goto end;

  sym = fcli_next_arg(1);
  fileName = fcli_next_arg(1);
  if(!sym || !*sym || !fileName || !*fileName){
    rc = fcli_err_set(FSL_RC_MISUSE,
                      "Usage: %s [options] CHECKIN_VERSION OUTPUT_FILE"
                      "\nOr try --help.",
                      fcli.appName);
    goto end;
  }

  rc = fsl_sym_to_uuid(f, sym, FSL_SATYPE_CHECKIN, &uuid, NULL);
  if(rc) goto end;

  if(!noRoot && !rootDir){
    char * pname;
    char * pz;
    pz = pname = fsl_config_get_text(f, FSL_CONFDB_REPO,
                                     "project-name", NULL);
    if(!pz){
      pz = pname = fsl_mprintf("Unnamed Project");
    }
    /* Translate unusual characters to underscores... */
    for( ; *pz; ++pz ){
      if('_'!=*pz && '-'!=*pz
         && !fsl_isalnum(*pz)){
        *pz = '_';
      }
    }
    pz = fsl_mprintf("%s-%.12s", pname, uuid);
    fcli_fax(pz);
    rootDir = pz;
    fsl_free(pname);
  }

  if(vbose){
    f_out("Extracting repository version %.12s to file %s...\n",
          uuid, fileName);
  }
  rc = fsl_repo_zip_sym_to_filename(f, sym, noRoot ? NULL : rootDir,
                                    fileName,
                                    vbose ? fsl_card_F_visitor_progress : NULL,
                                    &fileCounter);
  if(vbose && !rc){
    f_out("%d file(s) zipped to %s\n", fileCounter, fileName);
  }
  end:
  fsl_free(uuid);
  return fcli_end_of_main(rc);
}