Fossil

Diff
Login

Diff

Differences From Artifact [1ebd6da35f]:

To Artifact [2da0b425cc]:


538
539
540
541
542
543
544





545
546
547
548
549
550
551
  zName[i] = 0;
}


static struct{
  const char *zMasterName;    /* Name of master branch */
  int authorFlag;             /* Use author as checkin committer */





} ggit;

/*
** Read the git-fast-import format from pIn and insert the corresponding
** content into the database.
*/
static void git_fast_import(FILE *pIn){







>
>
>
>
>







538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
  zName[i] = 0;
}


static struct{
  const char *zMasterName;    /* Name of master branch */
  int authorFlag;             /* Use author as checkin committer */
  int nGitAttr;               /* Number of Git --attribute entries */
  struct {                    /* Git --attribute details */
    char *zUser;
    char *zEmail;
  } *gitUserInfo;
} ggit;

/*
** Read the git-fast-import format from pIn and insert the corresponding
** content into the database.
*/
static void git_fast_import(FILE *pIn){
662
663
664
665
666
667
668

669



670
671
672
673
674
675
676
677
678
679




680
681
682
683
684
685
686
        || (ggit.authorFlag && strncmp(zLine, "author ", 7)==0)
        || strncmp(zLine, "committer ",10)==0 ){
      sqlite3_int64 secSince1970;
      z = strchr(zLine, ' ');
      while( fossil_isspace(*z) ) z++;
      if( (zTo=strchr(z, '>'))==NULL ) goto malformed_line;
      *(++zTo) = '\0';

      /* Lookup user by contact info. */



      fossil_free(gg.zUser);
      gg.zUser = db_text(0, "SELECT login FROM user WHERE info=%Q", z);
      if( gg.zUser==NULL ){
        /* If there is no user with this contact info,
         * then use the email address as the username. */
        if ( (z=strchr(z, '<'))==NULL ) goto malformed_line;
        z++;
        *(zTo-1) = '\0';
        gg.zUser = fossil_strdup(z);
      }




      secSince1970 = 0;
      for(zTo++; fossil_isdigit(*zTo); zTo++){
        secSince1970 = secSince1970*10 + *zTo - '0';
      }
      fossil_free(gg.zDate);
      gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')",secSince1970);
      gg.zDate[10] = 'T';







>
|
>
>
>










>
>
>
>







667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
        || (ggit.authorFlag && strncmp(zLine, "author ", 7)==0)
        || strncmp(zLine, "committer ",10)==0 ){
      sqlite3_int64 secSince1970;
      z = strchr(zLine, ' ');
      while( fossil_isspace(*z) ) z++;
      if( (zTo=strchr(z, '>'))==NULL ) goto malformed_line;
      *(++zTo) = '\0';
      /*
      ** If --attribute requested, lookup user in fx_ table by email address,
      ** otherwise lookup Git {author,committer} contact info in user table. If
      ** no matches, use email address as username for check-in attribution.
      */
      fossil_free(gg.zUser);
      gg.zUser = db_text(0, "SELECT login FROM user WHERE info=%Q", z);
      if( gg.zUser==NULL ){
        /* If there is no user with this contact info,
         * then use the email address as the username. */
        if ( (z=strchr(z, '<'))==NULL ) goto malformed_line;
        z++;
        *(zTo-1) = '\0';
        gg.zUser = fossil_strdup(z);
      }
      if (ggit.nGitAttr > 0) {
        gg.zUser = db_text(gg.zUser,
         "SELECT user FROM fx_git WHERE email=%Q", z);
      }
      secSince1970 = 0;
      for(zTo++; fossil_isdigit(*zTo); zTo++){
        secSince1970 = secSince1970*10 + *zTo - '0';
      }
      fossil_free(gg.zDate);
      gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')",secSince1970);
      gg.zDate[10] = 'T';
1646
1647
1648
1649
1650
1651
1652


1653
1654
1655
1656
1657
1658
1659
**
**   --git        Import from the git-fast-export file format (default)
**                Options:
**                  --import-marks  FILE Restore marks table from FILE
**                  --export-marks  FILE Save marks table to FILE
**                  --rename-master NAME Renames the master branch to NAME
**                  --use-author    Uses author as the committer


**
**   --svn        Import from the svnadmin-dump file format.  The default
**                behaviour (unless overridden by --flat) is to treat 3
**                folders in the SVN root as special, following the
**                common layout of SVN repositories.  These are (by
**                default) trunk/, branches/ and tags/.  The SVN --deltas
**                format is supported but not required.







>
>







1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
**
**   --git        Import from the git-fast-export file format (default)
**                Options:
**                  --import-marks  FILE Restore marks table from FILE
**                  --export-marks  FILE Save marks table to FILE
**                  --rename-master NAME Renames the master branch to NAME
**                  --use-author    Uses author as the committer
**                  --attribute     "EMAIL USER" Attribute commits to USER
**                                  instead of Git committer EMAIL address
**
**   --svn        Import from the svnadmin-dump file format.  The default
**                behaviour (unless overridden by --flat) is to treat 3
**                folders in the SVN root as special, following the
**                common layout of SVN repositories.  These are (by
**                default) trunk/, branches/ and tags/.  The SVN --deltas
**                format is supported but not required.
1688
1689
1690
1691
1692
1693
1694





1695
1696
1697
1698
1699
1700
1701
** with the original name.  For example, "--rename-tag svn-%-tag" renames
** the tag called "release" to "svn-release-tag".
**
** --ignore-tree is useful for importing Subversion repositories which
** move branches to subdirectories of "branches/deleted" instead of
** deleting them.  It can be supplied multiple times if necessary.
**





** See also: export
*/
void import_cmd(void){
  char *zPassword;
  FILE *pIn;
  Stmt q;
  int forceFlag = find_option("force", "f", 0)!=0;







>
>
>
>
>







1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
** with the original name.  For example, "--rename-tag svn-%-tag" renames
** the tag called "release" to "svn-release-tag".
**
** --ignore-tree is useful for importing Subversion repositories which
** move branches to subdirectories of "branches/deleted" instead of
** deleting them.  It can be supplied multiple times if necessary.
**
** The --attribute option takes a quoted string argument comprised of a
** Git committer email and the username to be attributed to corresponding
** check-ins in the Fossil repository. This option can be repeated. For
** example, --attribute "drh@sqlite.org drh" --attribute "xyz@abc.net X"
**
** See also: export
*/
void import_cmd(void){
  char *zPassword;
  FILE *pIn;
  Stmt q;
  int forceFlag = find_option("force", "f", 0)!=0;
1774
1775
1776
1777
1778
1779
1780













1781
1782
1783
1784
1785
1786
1787
  }else if( gitFlag ){
    markfile_in = find_option("import-marks", 0, 1);
    markfile_out = find_option("export-marks", 0, 1);
    if( !(ggit.zMasterName = find_option("rename-master", 0, 1)) ){
      ggit.zMasterName = "master";
    }
    ggit.authorFlag = find_option("use-author", 0, 0)!=0;













  }
  verify_all_options();

  if( g.argc!=3 && g.argc!=4 ){
    usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
  }
  if( g.argc==4 ){







>
>
>
>
>
>
>
>
>
>
>
>
>







1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
  }else if( gitFlag ){
    markfile_in = find_option("import-marks", 0, 1);
    markfile_out = find_option("export-marks", 0, 1);
    if( !(ggit.zMasterName = find_option("rename-master", 0, 1)) ){
      ggit.zMasterName = "master";
    }
    ggit.authorFlag = find_option("use-author", 0, 0)!=0;
    /*
    ** Extract --attribute 'emailaddr username' args that will populate
    ** new 'fx_' table to later match username for check-in attribution.
    */
    const char *zGitUser = find_option("attribute", 0, 1);
    while( zGitUser != 0 ){
      ggit.gitUserInfo = fossil_realloc(ggit.gitUserInfo, ++ggit.nGitAttr
       * sizeof(ggit.gitUserInfo[0]));
      char *currGitUser = fossil_strdup(zGitUser);
      ggit.gitUserInfo[ggit.nGitAttr-1].zEmail = next_token(&currGitUser);
      ggit.gitUserInfo[ggit.nGitAttr-1].zUser = rest_of_line(&currGitUser);
      zGitUser = find_option("attribute", 0, 1);
    }
  }
  verify_all_options();

  if( g.argc!=3 && g.argc!=4 ){
    usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
  }
  if( g.argc==4 ){
1899
1900
1901
1902
1903
1904
1905


















1906
1907
1908
1909
1910
1911
1912
      if( import_marks(f, &blobs, NULL, NULL)<0 ){
        fossil_fatal("error importing marks from file: %s", markfile_in);
      }
      fclose(f);
    }

    manifest_crosslink_begin();


















    git_fast_import(pIn);
    db_prepare(&q, "SELECT tcontent FROM xtag");
    while( db_step(&q)==SQLITE_ROW ){
      Blob record;
      db_ephemeral_blob(&q, 0, &record);
      fast_insert_content(&record, 0, 0, 0, 1);
      import_reset(0);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
      if( import_marks(f, &blobs, NULL, NULL)<0 ){
        fossil_fatal("error importing marks from file: %s", markfile_in);
      }
      fclose(f);
    }

    manifest_crosslink_begin();
    /*
    ** The following 'fx_' table is used to hold information needed for
    ** importing and exporting to attribute Fossil check-ins or Git commits
    ** to either a desired username or full contact information string.
    */
    if(ggit.nGitAttr > 0) {
      db_unprotect(PROTECT_ALL);
      db_multi_exec(
        "CREATE TABLE fx_git(user TEXT, email TEXT UNIQUE);"
      );
      for( int idx = 0; idx < ggit.nGitAttr; ++idx ){
        db_multi_exec(
            "INSERT OR IGNORE INTO fx_git(user, email) VALUES(%Q, %Q)",
            ggit.gitUserInfo[idx].zUser, ggit.gitUserInfo[idx].zEmail
        );
      }
      db_protect_pop();
    }
    git_fast_import(pIn);
    db_prepare(&q, "SELECT tcontent FROM xtag");
    while( db_step(&q)==SQLITE_ROW ){
      Blob record;
      db_ephemeral_blob(&q, 0, &record);
      fast_insert_content(&record, 0, 0, 0, 1);
      import_reset(0);