Fossil

Check-in [eb1b310f]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge latest change from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | hide-diff-on-vdiff_page
Files: files | file ages | folders
SHA1:eb1b310fc726649d97fae660226a73ee8a860409
User & Date: mgagnon 2013-10-26 19:17:55
Context
2013-11-13
03:51
Merge latest trunk. check-in: 17f6b655 user: mgagnon tags: hide-diff-on-vdiff_page
2013-10-26
19:17
Merge latest change from trunk. check-in: eb1b310f user: mgagnon tags: hide-diff-on-vdiff_page
09:06
Allow comment_print() to handle lines >400 characters. Add parameter "width" to print_timeline() function. check-in: b2455507 user: jan.nijtmans tags: trunk
2013-10-19
06:47
Change /vdiff page (used when clicking on 2 nodes on /timeline), so it honor the show-version-diffs settings. Just like the /ci page. Also add the "Hide diff" button to hide the diffs manually.

The /vdiff page can have a lot of files to diff depending on which version are selected, so the capability to show only list of files that change is very convenient to spot interesting files. check-in: d7dc4158 user: mgagnon tags: hide-diff-on-vdiff_page

Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/checkin.c.

988
989
990
991
992
993
994

995
996
997
998
999
1000

1001
1002
1003
1004
1005
1006
1007
....
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
....
1608
1609
1610
1611
1612
1613
1614

1615




1616
1617
1618
1619
1620
1621
1622
1623
  int nFBcard = 0;            /* Number of B-cards and F-cards */
  int i;                      /* Loop counter */
  const char *zColor;         /* Modified value of p->zColor */

  assert( pBaseline==0 || pBaseline->zBaseline==0 );
  assert( pBaseline==0 || zBaselineUuid!=0 );
  blob_zero(pOut);

  zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND "
    "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)",
    vid, vid);
  if( !zParentUuid ){
    fossil_fatal("Could not find a valid check-in for RID %d. "
                 "Possible checkout/repo mismatch.", vid);

  }
  if( pBaseline ){
    blob_appendf(pOut, "B %s\n", zBaselineUuid);
    manifest_file_rewind(pBaseline);
    pFile = manifest_file_next(pBaseline, 0);
    nFBcard++;
  }else{
................................................................................
    blob_appendf(pOut, "F %F\n", pFile->zName);
    pFile = manifest_file_next(pBaseline, 0);
    nFBcard++;
  }
  if( p->zMimetype && p->zMimetype[0] ){
    blob_appendf(pOut, "N %F\n", p->zMimetype);
  }
  if( zParentUuid ){
    blob_appendf(pOut, "P %s", zParentUuid);
    if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
    free(zParentUuid);
    db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
    while( db_step(&q)==SQLITE_ROW ){
      char *zMergeUuid;
      int mid = db_column_int(&q, 0);
................................................................................
    fossil_fatal("none of the selected files have changed; use "
                 "--allow-empty to override.");
  }

  /*
  ** Do not allow a commit that will cause a fork unless the --allow-fork
  ** or --force flags is used, or unless this is a private check-in.

  */




  if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
    && g.markPrivate==0 && !is_a_leaf(vid)
  ){
    fossil_fatal("would fork.  \"update\" first or use --allow-fork.");
  }

  /*
  ** Do not allow a commit against a closed leaf







>
|
|
|
|
|
|
>







 







|







 







>

>
>
>
>
|







988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
....
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
....
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
  int nFBcard = 0;            /* Number of B-cards and F-cards */
  int i;                      /* Loop counter */
  const char *zColor;         /* Modified value of p->zColor */

  assert( pBaseline==0 || pBaseline->zBaseline==0 );
  assert( pBaseline==0 || zBaselineUuid!=0 );
  blob_zero(pOut);
  if( vid ){
    zParentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d AND "
      "EXISTS(SELECT 1 FROM event WHERE event.type='ci' and event.objid=%d)",
      vid, vid);
    if( !zParentUuid ){
      fossil_fatal("Could not find a valid check-in for RID %d. "
                   "Possible checkout/repo mismatch.", vid);
    }
  }
  if( pBaseline ){
    blob_appendf(pOut, "B %s\n", zBaselineUuid);
    manifest_file_rewind(pBaseline);
    pFile = manifest_file_next(pBaseline, 0);
    nFBcard++;
  }else{
................................................................................
    blob_appendf(pOut, "F %F\n", pFile->zName);
    pFile = manifest_file_next(pBaseline, 0);
    nFBcard++;
  }
  if( p->zMimetype && p->zMimetype[0] ){
    blob_appendf(pOut, "N %F\n", p->zMimetype);
  }
  if( vid ){
    blob_appendf(pOut, "P %s", zParentUuid);
    if( p->verifyDate ) checkin_verify_younger(vid, zParentUuid, zDate);
    free(zParentUuid);
    db_prepare(&q, "SELECT merge FROM vmerge WHERE id=0 OR id<-2");
    while( db_step(&q)==SQLITE_ROW ){
      char *zMergeUuid;
      int mid = db_column_int(&q, 0);
................................................................................
    fossil_fatal("none of the selected files have changed; use "
                 "--allow-empty to override.");
  }

  /*
  ** Do not allow a commit that will cause a fork unless the --allow-fork
  ** or --force flags is used, or unless this is a private check-in.
  ** The initial commit MUST have tags "trunk" and "sym-trunk".
  */
  if( !vid ){
    if( sCiInfo.zBranch==0 ){
      sCiInfo.zBranch = db_get("main-branch", "trunk");
    }
  }else if( sCiInfo.zBranch==0 && allowFork==0 && forceFlag==0
    && g.markPrivate==0 && !is_a_leaf(vid)
  ){
    fossil_fatal("would fork.  \"update\" first or use --allow-fork.");
  }

  /*
  ** Do not allow a commit against a closed leaf

Changes to src/comformat.c.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41





42
43
44
45
46
47
48

49
50
51
52
53
54
55

/*
** Given a comment string zText, format that string for printing
** on a TTY.  Assume that the output cursors is indent spaces from
** the left margin and that a single line can contain no more than
** lineLength characters.  Indent all subsequent lines by indent.
**
** lineLength must be less than 400.
**
** Return the number of newlines that are output.
*/
int comment_print(const char *zText, int indent, int lineLength){
  int tlen = lineLength - indent;
  int si, sk, i, k;
  int doIndent = 0;

  char zBuf[400];
  int lineCnt = 0; 






  for(;;){
    while( fossil_isspace(zText[0]) ){ zText++; }
    if( zText[0]==0 ){
      if( doIndent==0 ){
        fossil_print("\n");
        lineCnt = 1;
      }

      return lineCnt;
    }
    for(sk=si=i=k=0; zText[i] && k<tlen; i++){
      char c = zText[i];
      if( fossil_isspace(c) ){
        si = i;
        sk = k;







<
<






>
|


>
>
>
>
>







>







24
25
26
27
28
29
30


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

/*
** Given a comment string zText, format that string for printing
** on a TTY.  Assume that the output cursors is indent spaces from
** the left margin and that a single line can contain no more than
** lineLength characters.  Indent all subsequent lines by indent.
**


** Return the number of newlines that are output.
*/
int comment_print(const char *zText, int indent, int lineLength){
  int tlen = lineLength - indent;
  int si, sk, i, k;
  int doIndent = 0;
  char *zBuf;
  char zBuffer[400];
  int lineCnt = 0; 

  if( lineLength > sizeof(zBuffer) ){
    zBuf = fossil_malloc(lineLength);
  }else{
    zBuf = zBuffer;
  }
  for(;;){
    while( fossil_isspace(zText[0]) ){ zText++; }
    if( zText[0]==0 ){
      if( doIndent==0 ){
        fossil_print("\n");
        lineCnt = 1;
      }
      if( zBuf!=zBuffer) fossil_free(zBuf);
      return lineCnt;
    }
    for(sk=si=i=k=0; zText[i] && k<tlen; i++){
      char c = zText[i];
      if( fossil_isspace(c) ){
        si = i;
        sk = k;

Changes to src/config.h.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
*/
#define _LARGE_FILE       1
#ifndef _FILE_OFFSET_BITS
#  define _FILE_OFFSET_BITS 64
#endif
#define _LARGEFILE_SOURCE 1

/* Make sure that in Win32 builds, _USE_32BIT_TIME_T is always defined. */
#if defined(_WIN32) && !defined(_WIN64) && !defined(_USE_32BIT_TIME_T)
#  define _USE_32BIT_TIME_T
#endif

#ifdef HAVE_AUTOCONFIG_H
#include "autoconfig.h"
#endif








|
|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
*/
#define _LARGE_FILE       1
#ifndef _FILE_OFFSET_BITS
#  define _FILE_OFFSET_BITS 64
#endif
#define _LARGEFILE_SOURCE 1

/* Make sure that in Win32 MinGW builds, _USE_32BIT_TIME_T is always defined. */
#if defined(_WIN32) && !defined(_WIN64) && !defined(_MSC_VER) && !defined(_USE_32BIT_TIME_T)
#  define _USE_32BIT_TIME_T
#endif

#ifdef HAVE_AUTOCONFIG_H
#include "autoconfig.h"
#endif

Changes to src/descendants.c.

327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  compute_leaves(base, 0);
  db_prepare(&q,
    "%s"
    "   AND event.objid IN (SELECT rid FROM leaves)"
    " ORDER BY event.mtime DESC",
    timeline_query_for_tty()
  );
  print_timeline(&q, 20, 0);
  db_finalize(&q);
}

/*
** COMMAND: leaves*
**
** Usage: %fossil leaves ?OPTIONS?







|







327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  compute_leaves(base, 0);
  db_prepare(&q,
    "%s"
    "   AND event.objid IN (SELECT rid FROM leaves)"
    " ORDER BY event.mtime DESC",
    timeline_query_for_tty()
  );
  print_timeline(&q, 20, 79, 0);
  db_finalize(&q);
}

/*
** COMMAND: leaves*
**
** Usage: %fossil leaves ?OPTIONS?

Changes to src/search.c.

223
224
225
226
227
228
229
230
231
232
  }
  blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
  if(nLimit>0){
    blob_appendf(&sql, "LIMIT %d", nLimit);
  }
  db_prepare(&q, blob_str(&sql));
  blob_reset(&sql);
  print_timeline(&q, 1000, 0);
  db_finalize(&q);
}







|


223
224
225
226
227
228
229
230
231
232
  }
  blob_append(&sql, "ORDER BY x DESC, date DESC ", -1);
  if(nLimit>0){
    blob_appendf(&sql, "LIMIT %d", nLimit);
  }
  db_prepare(&q, blob_str(&sql));
  blob_reset(&sql);
  print_timeline(&q, 1000, 79, 0);
  db_finalize(&q);
}

Changes to src/tag.c.

470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
          timeline_query_for_tty(), zType, tagid
        );
        if(nFindLimit>0){
          blob_appendf(&sql, " LIMIT %d", nFindLimit);
        }
        db_prepare(&q, "%s", blob_str(&sql));
        blob_reset(&sql);
        print_timeline(&q, 2000, 0);
        db_finalize(&q);
      }
    }
  }else

  if( strncmp(g.argv[2],"list",n)==0 ){
    Stmt q;







|







470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
          timeline_query_for_tty(), zType, tagid
        );
        if(nFindLimit>0){
          blob_appendf(&sql, " LIMIT %d", nFindLimit);
        }
        db_prepare(&q, "%s", blob_str(&sql));
        blob_reset(&sql);
        print_timeline(&q, 2000, 79, 0);
        db_finalize(&q);
      }
    }
  }else

  if( strncmp(g.argv[2],"list",n)==0 ){
    Stmt q;

Changes to src/timeline.c.

1497
1498
1499
1500
1501
1502
1503
1504



1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
....
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
....
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
....
1592
1593
1594
1595
1596
1597
1598

1599
1600
1601
1602
1603
1604
1605
....
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
  style_footer();
}

/*
** The input query q selects various records.  Print a human-readable
** summary of those records.
**
** Limit the number of entries printed to nLine.



**
** The query should return these columns:
**
**    0.  rid
**    1.  uuid
**    2.  Date/Time
**    3.  Comment string and user
**    4.  Number of non-merge children
**    5.  Number of parents
**    6.  mtime
**    7.  branch
*/
void print_timeline(Stmt *q, int mxLine, int verboseFlag){
  int nLine = 0;
  char zPrevDate[20];
  const char *zCurrentUuid=0;
  int fchngQueryInit = 0;     /* True if fchngQuery is initialized */
  Stmt fchngQuery;            /* Query for file changes on check-ins */
  zPrevDate[0] = 0;

  if( g.localOpen ){
    int rid = db_lget_int("checkout", 0);
    zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  }

  while( db_step(q)==SQLITE_ROW && nLine<=mxLine ){
    int rid = db_column_int(q, 0);
    const char *zId = db_column_text(q, 1);
    const char *zDate = db_column_text(q, 2);
    const char *zCom = db_column_text(q, 3);
    int nChild = db_column_int(q, 4);
    int nParent = db_column_int(q, 5);
    char *zFree = 0;
................................................................................
    char zPrefix[80];
    char zUuid[UUID_SIZE+1];

    sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId);
    if( memcmp(zDate, zPrevDate, 10) ){
      fossil_print("=== %.10s ===\n", zDate);
      memcpy(zPrevDate, zDate, 10);
      nLine++;
    }
    if( zCom==0 ) zCom = "";
    fossil_print("%.8s ", &zDate[11]);
    zPrefix[0] = 0;
    if( nParent>1 ){
      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
      n = strlen(zPrefix);
................................................................................
      n = strlen(zPrefix);
    }
    if( fossil_strcmp(zCurrentUuid,zId)==0 ){
      sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* ");
      n += strlen(zPrefix);
    }
    zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom);
    nLine += comment_print(zFree, 9, 79);
    sqlite3_free(zFree);

    if(verboseFlag){
      if( !fchngQueryInit ){
        db_prepare(&fchngQuery,
           "SELECT (pid==0) AS isnew,"
           "       (fid==0) AS isdel,"
................................................................................
        if( isNew ){
          fossil_print("   ADDED %s\n",zFilename);
        }else if( isDel ){
          fossil_print("   DELETED %s\n",zFilename);
        }else{
          fossil_print("   EDITED %s\n", zFilename);
        }

      }
      db_reset(&fchngQuery);
    }
  }
  if( fchngQueryInit ) db_finalize(&fchngQuery);
}

................................................................................
  }
  if( zType && (zType[0]!='a') ){
    blob_appendf(&sql, " AND event.type=%Q ", zType);
  }
  blob_appendf(&sql, " ORDER BY event.mtime DESC");
  db_prepare(&q, blob_str(&sql));
  blob_reset(&sql);
  print_timeline(&q, n, verboseFlag);
  db_finalize(&q);
}

/*
** This is a version of the "localtime()" function from the standard
** C library.  It converts a unix timestamp (seconds since 1970) into
** a broken-out local time structure.







|
>
>
>












|












|







 







|







 







|







 







>







 







|







1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
....
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
....
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
....
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
....
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
  style_footer();
}

/*
** The input query q selects various records.  Print a human-readable
** summary of those records.
**
** Limit the number of lines printed to mxLine.  If mxLine is zero or
** negative there is no limit.  The line limit is approximate because
** it is only checked on a per-entry basis.  In verbose mode, the file
** name details are considered to be part of the entry.
**
** The query should return these columns:
**
**    0.  rid
**    1.  uuid
**    2.  Date/Time
**    3.  Comment string and user
**    4.  Number of non-merge children
**    5.  Number of parents
**    6.  mtime
**    7.  branch
*/
void print_timeline(Stmt *q, int mxLine, int width, int verboseFlag){
  int nLine = 0;
  char zPrevDate[20];
  const char *zCurrentUuid=0;
  int fchngQueryInit = 0;     /* True if fchngQuery is initialized */
  Stmt fchngQuery;            /* Query for file changes on check-ins */
  zPrevDate[0] = 0;

  if( g.localOpen ){
    int rid = db_lget_int("checkout", 0);
    zCurrentUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  }

  while( db_step(q)==SQLITE_ROW && (mxLine<=0 || nLine<=mxLine) ){
    int rid = db_column_int(q, 0);
    const char *zId = db_column_text(q, 1);
    const char *zDate = db_column_text(q, 2);
    const char *zCom = db_column_text(q, 3);
    int nChild = db_column_int(q, 4);
    int nParent = db_column_int(q, 5);
    char *zFree = 0;
................................................................................
    char zPrefix[80];
    char zUuid[UUID_SIZE+1];

    sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId);
    if( memcmp(zDate, zPrevDate, 10) ){
      fossil_print("=== %.10s ===\n", zDate);
      memcpy(zPrevDate, zDate, 10);
      nLine++; /* record another line */
    }
    if( zCom==0 ) zCom = "";
    fossil_print("%.8s ", &zDate[11]);
    zPrefix[0] = 0;
    if( nParent>1 ){
      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "*MERGE* ");
      n = strlen(zPrefix);
................................................................................
      n = strlen(zPrefix);
    }
    if( fossil_strcmp(zCurrentUuid,zId)==0 ){
      sqlite3_snprintf(sizeof(zPrefix)-n, &zPrefix[n], "*CURRENT* ");
      n += strlen(zPrefix);
    }
    zFree = sqlite3_mprintf("[%.10s] %s%s", zUuid, zPrefix, zCom);
    nLine += comment_print(zFree, 9, width); /* record another X lines */
    sqlite3_free(zFree);

    if(verboseFlag){
      if( !fchngQueryInit ){
        db_prepare(&fchngQuery,
           "SELECT (pid==0) AS isnew,"
           "       (fid==0) AS isdel,"
................................................................................
        if( isNew ){
          fossil_print("   ADDED %s\n",zFilename);
        }else if( isDel ){
          fossil_print("   DELETED %s\n",zFilename);
        }else{
          fossil_print("   EDITED %s\n", zFilename);
        }
        nLine++; /* record another line */
      }
      db_reset(&fchngQuery);
    }
  }
  if( fchngQueryInit ) db_finalize(&fchngQuery);
}

................................................................................
  }
  if( zType && (zType[0]!='a') ){
    blob_appendf(&sql, " AND event.type=%Q ", zType);
  }
  blob_appendf(&sql, " ORDER BY event.mtime DESC");
  db_prepare(&q, blob_str(&sql));
  blob_reset(&sql);
  print_timeline(&q, n, 79, verboseFlag);
  db_finalize(&q);
}

/*
** This is a version of the "localtime()" function from the standard
** C library.  It converts a unix timestamp (seconds since 1970) into
** a broken-out local time structure.

Changes to src/update.c.

186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
        compute_leaves(vid, closeCode);
        db_prepare(&q, 
          "%s "
          "   AND event.objid IN leaves"
          " ORDER BY event.mtime DESC",
          timeline_query_for_tty()
        );
        print_timeline(&q, 100, 0);
        db_finalize(&q);
        fossil_fatal("Multiple descendants");
      }
    }
    tid = db_int(0, "SELECT rid FROM leaves, event"
                    " WHERE event.objid=leaves.rid"
                    " ORDER BY event.mtime DESC"); 







|







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
        compute_leaves(vid, closeCode);
        db_prepare(&q, 
          "%s "
          "   AND event.objid IN leaves"
          " ORDER BY event.mtime DESC",
          timeline_query_for_tty()
        );
        print_timeline(&q, 100, 79, 0);
        db_finalize(&q);
        fossil_fatal("Multiple descendants");
      }
    }
    tid = db_int(0, "SELECT rid FROM leaves, event"
                    " WHERE event.objid=leaves.rid"
                    " ORDER BY event.mtime DESC"); 

Changes to www/concepts.wiki.

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
at a repository and get human-readable status, history, and tracking
information about the project.

<h3>2.1 Identification Of Artifacts</h3>

A particular version of a particular file is called an "artifact".
Each artifact has a universally unique name which is the
<a href="http://en.wikipedia.org/wiki/SHA">SHA1</a> hash of the content
of that file expressed as 40 characters of lower-case hexadecimal.  Such
a hash is referred to as the Artifact Identifier or Artifact ID
for the artifact.  The SHA1 algorithm is created with the purpose of
providing a highly forgery-resistant identifier for a file.  Given any
file it is simple to find the artifact ID for that file.  But given a
artifact ID it is computationally intractable to generate a file that will
have that Artifact ID.







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
at a repository and get human-readable status, history, and tracking
information about the project.

<h3>2.1 Identification Of Artifacts</h3>

A particular version of a particular file is called an "artifact".
Each artifact has a universally unique name which is the
<a href="http://en.wikipedia.org/wiki/SHA1">SHA1</a> hash of the content
of that file expressed as 40 characters of lower-case hexadecimal.  Such
a hash is referred to as the Artifact Identifier or Artifact ID
for the artifact.  The SHA1 algorithm is created with the purpose of
providing a highly forgery-resistant identifier for a file.  Given any
file it is simple to find the artifact ID for that file.  But given a
artifact ID it is computationally intractable to generate a file that will
have that Artifact ID.