Diff
Not logged in

Differences From Artifact [7797f22924]:

To Artifact [13832766e9]:


33
34
35
36
37
38
39

40
41
42
43
44
45
46
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47







+







@ );
@ CREATE TABLE IF NOT EXISTS %s.stashfile(
@   stashid INTEGER REFERENCES stash,  -- Stash that contains this file
@   rid INTEGER,                       -- Baseline content in BLOB table or 0.
@   isAdded BOOLEAN,                   -- True if this is an added file
@   isRemoved BOOLEAN,                 -- True if this file is deleted
@   isExec BOOLEAN,                    -- True if file is executable
@   isLink BOOLEAN,                    -- True if file is a symlink
@   origname TEXT,                     -- Original filename
@   newname TEXT,                      -- New name for file at next check-in
@   delta BLOB,                        -- Delta from baseline. Content if rid=0
@   PRIMARY KEY(origname, stashid)
@ );
@ INSERT OR IGNORE INTO vvar(name, value) VALUES('stash-next', 1);
;
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

82
83

84
85
86
87

88
89
90



91
92

93
94
95
96
97
98

99
100
101

102
103



104


105
106
107
108
109
110
111




112


113
114
115
116
117
118

119
120
121
122
123
124
125
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

82
83

84
85
86
87
88
89



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140







-
+














-
+

-
+




+
-
-
-
+
+
+


+






+



+


+
+
+
-
+
+







+
+
+
+
-
+
+






+







  Stmt ins;             /* Insert statement */

  zFile = mprintf("%/", zFName);
  file_tree_name(zFile, &fname, 1);
  zTreename = blob_str(&fname);
  blob_zero(&sql);
  blob_appendf(&sql,
    "SELECT deleted, isexe, mrid, pathname, coalesce(origname,pathname)"
    "SELECT deleted, isexe, islink, mrid, pathname, coalesce(origname,pathname)"
    "  FROM vfile"
    " WHERE vid=%d AND (chnged OR deleted OR origname NOT NULL OR mrid==0)",
    vid
  );
  if( fossil_strcmp(zTreename,".")!=0 ){
    blob_appendf(&sql,
      "   AND (pathname GLOB '%q/*' OR origname GLOB '%q/*'"
            "  OR pathname=%Q OR origname=%Q)",
      zTreename, zTreename, zTreename, zTreename
    );
  }
  db_prepare(&q, blob_str(&sql));
  blob_reset(&sql);
  db_prepare(&ins,
     "INSERT INTO stashfile(stashid, rid, isAdded, isRemoved, isExec,"
     "INSERT INTO stashfile(stashid, rid, isAdded, isRemoved, isExec, isLink,"
                           "origname, newname, delta)"
     "VALUES(%d,:rid,:isadd,:isrm,:isexe,:orig,:new,:content)",
     "VALUES(%d,:rid,:isadd,:isrm,:isexe,:islink,:orig,:new,:content)",
     stashid
  );
  while( db_step(&q)==SQLITE_ROW ){
    int deleted = db_column_int(&q, 0);
    //int isLink = db_column_int(&q, 2);
    int rid = db_column_int(&q, 2);
    const char *zName = db_column_text(&q, 3);
    const char *zOrig = db_column_text(&q, 4);
    int rid = db_column_int(&q, 3);
    const char *zName = db_column_text(&q, 4);
    const char *zOrig = db_column_text(&q, 5);
    char *zPath = mprintf("%s%s", g.zLocalRoot, zName);
    Blob content;
    int isNewLink = file_islink(zPath);

    db_bind_int(&ins, ":rid", rid);
    db_bind_int(&ins, ":isadd", rid==0);
    db_bind_int(&ins, ":isrm", deleted);
#ifdef _WIN32
    db_bind_int(&ins, ":isexe", db_column_int(&q, 1));
    //db_bind_int(&ins, ":islink", isLink);
#endif
    db_bind_text(&ins, ":orig", zOrig);
    db_bind_text(&ins, ":new", zName);

    if( rid==0 ){
      /* A new file */
      if( isNewLink ){
        blob_read_link(&content, zPath);
      }else{
      blob_read_from_file(&content, zPath);
        blob_read_from_file(&content, zPath);
      }
      db_bind_blob(&ins, ":content", &content);
    }else if( deleted ){
      db_bind_null(&ins, ":content");
    }else{
      /* A modified file */
      Blob orig;
      Blob disk;
      
      if( isNewLink ){
        blob_read_link(&disk, zPath);
      }else{
      blob_read_from_file(&disk, zPath);
        blob_read_from_file(&disk, zPath);
      }
      content_get(rid, &orig);
      blob_delta_create(&orig, &disk, &content);
      blob_reset(&orig);
      blob_reset(&disk);
      db_bind_blob(&ins, ":content", &content);
    }
    db_bind_int(&ins, ":islink", isNewLink);
    db_step(&ins);
    db_reset(&ins);
    fossil_free(zPath);
    blob_reset(&content);
  }
  db_finalize(&ins);
  db_finalize(&q);
166
167
168
169
170
171
172
173

174
175
176
177
178
179

180
181


182
183
184
185
186
187
188
189
190
191
192
193
194
195

196



197


198
199
200
201









202
203






204
205




206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226


227
228
229
230
231
232
233
234
235
236
237
238

239
240
241
242
243
244

245
246


247
248
249
250
251
252
253
254
255



256


257
258
259
260

261



262
263
264










265
266
267
268




269
270
271
272
273
274
275
181
182
183
184
185
186
187

188
189
190
191
192
193
194
195


196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

217
218
219
220


221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237


238
239
240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255
256
257
258
259
260

261
262
263
264
265
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
281


282
283
284
285
286
287
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303
304
305
306



307
308
309
310
311
312
313
314
315
316




317
318
319
320
321
322
323
324
325
326
327







-
+






+
-
-
+
+














+

+
+
+
-
+
+


-
-
+
+
+
+
+
+
+
+
+


+
+
+
+
+
+
-
-
+
+
+
+






-













-
+
+











-
+






+
-
-
+
+









+
+
+
-
+
+




+

+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+








/*
** Apply a stash to the current check-out.
*/
static void stash_apply(int stashid, int nConflict){
  Stmt q;
  db_prepare(&q,
     "SELECT rid, isRemoved, isExec, origname, newname, delta"
     "SELECT rid, isRemoved, isExec, isLink, origname, newname, delta"
     "  FROM stashfile WHERE stashid=%d",
     stashid
  );
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    int isRemoved = db_column_int(&q, 1);
    int isLink = db_column_int(&q, 3);
    const char *zOrig = db_column_text(&q, 3);
    const char *zNew = db_column_text(&q, 4);
    const char *zOrig = db_column_text(&q, 4);
    const char *zNew = db_column_text(&q, 5);
    char *zOPath = mprintf("%s%s", g.zLocalRoot, zOrig);
    char *zNPath = mprintf("%s%s", g.zLocalRoot, zNew);
    Blob delta;
    undo_save(zNew);
    blob_zero(&delta);
    if( rid==0 ){
      db_ephemeral_blob(&q, 5, &delta);
      blob_write_to_file(&delta, zNPath);
      printf("ADD %s\n", zNew);
    }else if( isRemoved ){
      printf("DELETE %s\n", zOrig);
      unlink(zOPath);
    }else{
      Blob a, b, out, disk;
      int isNewLink = file_islink(zOPath);
      db_ephemeral_blob(&q, 5, &delta);
      if( isNewLink ){
        blob_read_link(&disk, zOPath);
      }else{
      blob_read_from_file(&disk, zOPath);     
        blob_read_from_file(&disk, zOPath);
      }
      content_get(rid, &a);
      blob_delta_apply(&a, &delta, &b);
      if( blob_compare(&disk, &a)==0 ){
        blob_write_to_file(&b, zNPath);
      if( blob_compare(&disk, &a)==0 && isLink == isNewLink ){
        if( isLink || isNewLink ){
          unlink(zNPath);
        }
        if( isLink ){
          create_symlink(blob_str(&b), zNPath);
        }else{
          blob_write_to_file(&b, zNPath);          
        }
        printf("UPDATE %s\n", zNew);
      }else{
        int rc;
        if( isLink || isNewLink ){
          rc = -1;
          blob_zero(&b); /* because we reset it later */
          //TODO write something to disk?
        }else{
        int rc = blob_merge(&a, &disk, &b, &out);
        blob_write_to_file(&out, zNPath);
          rc = blob_merge(&a, &disk, &b, &out);
          blob_write_to_file(&out, zNPath);          
          blob_reset(&out);
        }
        if( rc ){
          printf("CONFLICT %s\n", zNew);
          nConflict++;
        }else{
          printf("MERGE %s\n", zNew);
        }
        blob_reset(&out);
      }
      blob_reset(&a);
      blob_reset(&b);
      blob_reset(&disk);
    }
    blob_reset(&delta);
    if( fossil_strcmp(zOrig,zNew)!=0 ){
      undo_save(zOrig);
      unlink(zOPath);
    }
  }
  db_finalize(&q);
  if( nConflict ){
    printf("WARNING: merge conflicts - see messages above for details.\n");
    printf("WARNING: %d merge conflicts - see messages above for details.\n",
            nConflict);
  }
}

/*
** Show the diffs associate with a single stash.
*/
static void stash_diff(int stashid, const char *zDiffCmd){
  Stmt q;
  Blob empty;
  blob_zero(&empty);
  db_prepare(&q,
     "SELECT rid, isRemoved, isExec, origname, newname, delta"
     "SELECT rid, isRemoved, isExec, isLink, origname, newname, delta"
     "  FROM stashfile WHERE stashid=%d",
     stashid
  );
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    int isRemoved = db_column_int(&q, 1);
    int isLink = db_column_int(&q, 3);
    const char *zOrig = db_column_text(&q, 3);
    const char *zNew = db_column_text(&q, 4);
    const char *zOrig = db_column_text(&q, 4);
    const char *zNew = db_column_text(&q, 5);
    char *zOPath = mprintf("%s%s", g.zLocalRoot, zOrig);
    Blob delta;
    if( rid==0 ){
      db_ephemeral_blob(&q, 5, &delta);
      printf("ADDED %s\n", zNew);
      diff_print_index(zNew);
      diff_file_mem(&empty, &delta, zNew, zDiffCmd, 0);
    }else if( isRemoved ){
      printf("DELETE %s\n", zOrig);
      if( file_islink(zOPath) ){
        blob_read_link(&delta, zOPath);
      }else{
      blob_read_from_file(&delta, zOPath);
        blob_read_from_file(&delta, zOPath);
      }
      diff_print_index(zNew);
      diff_file_mem(&delta, &empty, zOrig, zDiffCmd, 0);
    }else{
      Blob a, b, disk;
      int isOrigLink = file_islink(zOPath);
      db_ephemeral_blob(&q, 5, &delta);
      if( isOrigLink ){
        blob_read_link(&disk, zOPath);
      }else{
      blob_read_from_file(&disk, zOPath);     
      content_get(rid, &a);
      blob_delta_apply(&a, &delta, &b);
        blob_read_from_file(&disk, zOPath);        
      }
      printf("CHANGED %s\n", zNew);
      if( !isOrigLink != !isLink ){
        diff_print_index(zNew);
        printf("--- %s\n+++ %s\n", zOrig, zNew);
        printf("cannot compute difference between symlink and regular file\n");
      }else{
        content_get(rid, &a);
        blob_delta_apply(&a, &delta, &b);
      printf("CHANGED %s\n", zNew);
      diff_file_mem(&disk, &b, zNew, zDiffCmd, 0);
      blob_reset(&a);
      blob_reset(&b);
        diff_file_mem(&disk, &b, zNew, zDiffCmd, 0);
        blob_reset(&a);
        blob_reset(&b);
      }
      blob_reset(&disk);
    }
    blob_reset(&delta);
 }
  db_finalize(&q);
}

345
346
347
348
349
350
351
352

353
354
355
356
357
358
359
397
398
399
400
401
402
403

404
405
406
407
408
409
410
411







-
+







**  fossil stash drop ?STASHID? ?--all?
**
**     Forget everything about STASHID.  Forget the whole stash if the
**     --all flag is used.  Individual drops are undoable but --all is not.
**
**  fossil stash snapshot ?-m COMMENT? ?FILES...?
**
**     Save the current changes in the working tress as a new stash
**     Save the current changes in the working tree as a new stash
**     but, unlike "save", do not revert those changes.
**
**  fossil stash diff ?STASHID?
**  fossil stash gdiff ?STASHID?
**
**     Show diffs of the current working directory and what that
**     directory would be if STASHID were applied.