Mercurial > vim
comparison src/filepath.c @ 30150:0fe61fa4e5d1 v9.0.0411
patch 9.0.0411: only created files can be cleaned up with one call
Commit: https://github.com/vim/vim/commit/6f14da15ac900589f2f413d77898b9bff3b31ece
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Sep 7 21:30:44 2022 +0100
patch 9.0.0411: only created files can be cleaned up with one call
Problem: Only created files can be cleaned up with one call.
Solution: Add flags to mkdir() to delete with a deferred function.
Expand the writefile() name to a full path to handle changing
directory.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 07 Sep 2022 22:45:04 +0200 |
parents | a542dfb1c1a2 |
children | b3de17181c19 |
comparison
equal
deleted
inserted
replaced
30149:58dd17222e56 | 30150:0fe61fa4e5d1 |
---|---|
1426 } | 1426 } |
1427 | 1427 |
1428 /* | 1428 /* |
1429 * Create the directory in which "dir" is located, and higher levels when | 1429 * Create the directory in which "dir" is located, and higher levels when |
1430 * needed. | 1430 * needed. |
1431 * Set "created" to the full name of the first created directory. It will be | |
1432 * NULL until that happens. | |
1431 * Return OK or FAIL. | 1433 * Return OK or FAIL. |
1432 */ | 1434 */ |
1433 static int | 1435 static int |
1434 mkdir_recurse(char_u *dir, int prot) | 1436 mkdir_recurse(char_u *dir, int prot, char_u **created) |
1435 { | 1437 { |
1436 char_u *p; | 1438 char_u *p; |
1437 char_u *updir; | 1439 char_u *updir; |
1438 int r = FAIL; | 1440 int r = FAIL; |
1439 | 1441 |
1447 updir = vim_strnsave(dir, p - dir); | 1449 updir = vim_strnsave(dir, p - dir); |
1448 if (updir == NULL) | 1450 if (updir == NULL) |
1449 return FAIL; | 1451 return FAIL; |
1450 if (mch_isdir(updir)) | 1452 if (mch_isdir(updir)) |
1451 r = OK; | 1453 r = OK; |
1452 else if (mkdir_recurse(updir, prot) == OK) | 1454 else if (mkdir_recurse(updir, prot, created) == OK) |
1455 { | |
1453 r = vim_mkdir_emsg(updir, prot); | 1456 r = vim_mkdir_emsg(updir, prot); |
1457 if (r == OK && created != NULL && *created == NULL) | |
1458 *created = FullName_save(updir, FALSE); | |
1459 } | |
1454 vim_free(updir); | 1460 vim_free(updir); |
1455 return r; | 1461 return r; |
1456 } | 1462 } |
1457 | 1463 |
1458 /* | 1464 /* |
1462 f_mkdir(typval_T *argvars, typval_T *rettv) | 1468 f_mkdir(typval_T *argvars, typval_T *rettv) |
1463 { | 1469 { |
1464 char_u *dir; | 1470 char_u *dir; |
1465 char_u buf[NUMBUFLEN]; | 1471 char_u buf[NUMBUFLEN]; |
1466 int prot = 0755; | 1472 int prot = 0755; |
1473 int defer = FALSE; | |
1474 int defer_recurse = FALSE; | |
1475 char_u *created = NULL; | |
1467 | 1476 |
1468 rettv->vval.v_number = FAIL; | 1477 rettv->vval.v_number = FAIL; |
1469 if (check_restricted() || check_secure()) | 1478 if (check_restricted() || check_secure()) |
1470 return; | 1479 return; |
1471 | 1480 |
1484 // remove trailing slashes | 1493 // remove trailing slashes |
1485 *gettail_sep(dir) = NUL; | 1494 *gettail_sep(dir) = NUL; |
1486 | 1495 |
1487 if (argvars[1].v_type != VAR_UNKNOWN) | 1496 if (argvars[1].v_type != VAR_UNKNOWN) |
1488 { | 1497 { |
1498 char_u *arg2; | |
1499 | |
1489 if (argvars[2].v_type != VAR_UNKNOWN) | 1500 if (argvars[2].v_type != VAR_UNKNOWN) |
1490 { | 1501 { |
1491 prot = (int)tv_get_number_chk(&argvars[2], NULL); | 1502 prot = (int)tv_get_number_chk(&argvars[2], NULL); |
1492 if (prot == -1) | 1503 if (prot == -1) |
1493 return; | 1504 return; |
1494 } | 1505 } |
1495 if (STRCMP(tv_get_string(&argvars[1]), "p") == 0) | 1506 arg2 = tv_get_string(&argvars[1]); |
1507 defer = vim_strchr(arg2, 'D') != NULL; | |
1508 defer_recurse = vim_strchr(arg2, 'R') != NULL; | |
1509 if ((defer || defer_recurse) && !can_add_defer()) | |
1510 return; | |
1511 | |
1512 if (vim_strchr(arg2, 'p') != NULL) | |
1496 { | 1513 { |
1497 if (mch_isdir(dir)) | 1514 if (mch_isdir(dir)) |
1498 { | 1515 { |
1499 // With the "p" flag it's OK if the dir already exists. | 1516 // With the "p" flag it's OK if the dir already exists. |
1500 rettv->vval.v_number = OK; | 1517 rettv->vval.v_number = OK; |
1501 return; | 1518 return; |
1502 } | 1519 } |
1503 mkdir_recurse(dir, prot); | 1520 mkdir_recurse(dir, prot, defer || defer_recurse ? &created : NULL); |
1504 } | 1521 } |
1505 } | 1522 } |
1506 rettv->vval.v_number = vim_mkdir_emsg(dir, prot); | 1523 rettv->vval.v_number = vim_mkdir_emsg(dir, prot); |
1524 | |
1525 // Handle "D" and "R": deferred deletion of the created directory. | |
1526 if (rettv->vval.v_number == OK | |
1527 && created == NULL && (defer || defer_recurse)) | |
1528 created = FullName_save(dir, FALSE); | |
1529 if (created != NULL) | |
1530 { | |
1531 typval_T tv[2]; | |
1532 | |
1533 tv[0].v_type = VAR_STRING; | |
1534 tv[0].v_lock = 0; | |
1535 tv[0].vval.v_string = created; | |
1536 tv[1].v_type = VAR_STRING; | |
1537 tv[1].v_lock = 0; | |
1538 tv[1].vval.v_string = vim_strsave( | |
1539 (char_u *)(defer_recurse ? "rf" : "d")); | |
1540 if (tv[0].vval.v_string == NULL || tv[1].vval.v_string == NULL | |
1541 || add_defer((char_u *)"delete", 2, tv) == FAIL) | |
1542 { | |
1543 vim_free(tv[0].vval.v_string); | |
1544 vim_free(tv[1].vval.v_string); | |
1545 } | |
1546 } | |
1507 } | 1547 } |
1508 | 1548 |
1509 /* | 1549 /* |
1510 * "pathshorten()" function | 1550 * "pathshorten()" function |
1511 */ | 1551 */ |
2298 | 2338 |
2299 fname = tv_get_string_chk(&argvars[1]); | 2339 fname = tv_get_string_chk(&argvars[1]); |
2300 if (fname == NULL) | 2340 if (fname == NULL) |
2301 return; | 2341 return; |
2302 | 2342 |
2303 if (defer && !in_def_function() && get_current_funccal() == NULL) | 2343 if (defer && !can_add_defer()) |
2304 { | 2344 return; |
2305 semsg(_(e_str_not_inside_function), "defer"); | |
2306 return; | |
2307 } | |
2308 | 2345 |
2309 // Always open the file in binary mode, library functions have a mind of | 2346 // Always open the file in binary mode, library functions have a mind of |
2310 // their own about CR-LF conversion. | 2347 // their own about CR-LF conversion. |
2311 if (*fname == NUL || (fd = mch_fopen((char *)fname, | 2348 if (*fname == NUL || (fd = mch_fopen((char *)fname, |
2312 append ? APPENDBIN : WRITEBIN)) == NULL) | 2349 append ? APPENDBIN : WRITEBIN)) == NULL) |
2321 { | 2358 { |
2322 typval_T tv; | 2359 typval_T tv; |
2323 | 2360 |
2324 tv.v_type = VAR_STRING; | 2361 tv.v_type = VAR_STRING; |
2325 tv.v_lock = 0; | 2362 tv.v_lock = 0; |
2326 tv.vval.v_string = vim_strsave(fname); | 2363 tv.vval.v_string = FullName_save(fname, FALSE); |
2327 if (tv.vval.v_string == NULL | 2364 if (tv.vval.v_string == NULL |
2328 || add_defer((char_u *)"delete", 1, &tv) == FAIL) | 2365 || add_defer((char_u *)"delete", 1, &tv) == FAIL) |
2329 { | 2366 { |
2330 ret = -1; | 2367 ret = -1; |
2331 fclose(fd); | 2368 fclose(fd); |