unstow_orig.t 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. #!/usr/bin/perl
  2. #
  3. # This file is part of GNU Stow.
  4. #
  5. # GNU Stow is free software: you can redistribute it and/or modify it
  6. # under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # GNU Stow is distributed in the hope that it will be useful, but
  11. # WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. # General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see https://www.gnu.org/licenses/.
  17. #
  18. # Test unstowing packages in compat mode
  19. #
  20. use strict;
  21. use warnings;
  22. use File::Spec qw(make_path);
  23. use Test::More tests => 37;
  24. use Test::Output;
  25. use English qw(-no_match_vars);
  26. use testutil;
  27. use Stow::Util qw(canon_path);
  28. init_test_dirs();
  29. cd("$TEST_DIR/target");
  30. # Note that each of the following tests use a distinct set of files
  31. my $stow;
  32. my %conflicts;
  33. #
  34. # unstow a simple tree minimally
  35. #
  36. $stow = new_compat_Stow();
  37. make_path('../stow/pkg1/bin1');
  38. make_file('../stow/pkg1/bin1/file1');
  39. make_link('bin1', '../stow/pkg1/bin1');
  40. $stow->plan_unstow('pkg1');
  41. $stow->process_tasks();
  42. ok(
  43. $stow->get_conflict_count == 0 &&
  44. -f '../stow/pkg1/bin1/file1' && ! -e 'bin1'
  45. => 'unstow a simple tree'
  46. );
  47. #
  48. # unstow a simple tree from an existing directory
  49. #
  50. $stow = new_compat_Stow();
  51. make_path('lib2');
  52. make_path('../stow/pkg2/lib2');
  53. make_file('../stow/pkg2/lib2/file2');
  54. make_link('lib2/file2', '../../stow/pkg2/lib2/file2');
  55. $stow->plan_unstow('pkg2');
  56. $stow->process_tasks();
  57. ok(
  58. $stow->get_conflict_count == 0 &&
  59. -f '../stow/pkg2/lib2/file2' && -d 'lib2'
  60. => 'unstow simple tree from a pre-existing directory'
  61. );
  62. #
  63. # fold tree after unstowing
  64. #
  65. $stow = new_compat_Stow();
  66. make_path('bin3');
  67. make_path('../stow/pkg3a/bin3');
  68. make_file('../stow/pkg3a/bin3/file3a');
  69. make_link('bin3/file3a' => '../../stow/pkg3a/bin3/file3a'); # emulate stow
  70. make_path('../stow/pkg3b/bin3');
  71. make_file('../stow/pkg3b/bin3/file3b');
  72. make_link('bin3/file3b' => '../../stow/pkg3b/bin3/file3b'); # emulate stow
  73. $stow->plan_unstow('pkg3b');
  74. $stow->process_tasks();
  75. ok(
  76. $stow->get_conflict_count == 0 &&
  77. -l 'bin3' &&
  78. readlink('bin3') eq '../stow/pkg3a/bin3'
  79. => 'fold tree after unstowing'
  80. );
  81. #
  82. # existing link is owned by stow but is invalid so it gets removed anyway
  83. #
  84. $stow = new_compat_Stow();
  85. make_path('bin4');
  86. make_path('../stow/pkg4/bin4');
  87. make_file('../stow/pkg4/bin4/file4');
  88. make_invalid_link('bin4/file4', '../../stow/pkg4/bin4/does-not-exist');
  89. $stow->plan_unstow('pkg4');
  90. $stow->process_tasks();
  91. ok(
  92. $stow->get_conflict_count == 0 &&
  93. ! -e 'bin4/file4'
  94. => q(remove invalid link owned by stow)
  95. );
  96. #
  97. # Existing link is not owned by stow
  98. #
  99. $stow = new_compat_Stow();
  100. make_path('../stow/pkg5/bin5');
  101. make_invalid_link('bin5', '../not-stow');
  102. $stow->plan_unstow('pkg5');
  103. # Unlike the corresponding stow_contents.t test, this doesn't
  104. # cause any conflicts.
  105. #
  106. #like(
  107. # $Conflicts[-1], qr(can't unlink.*not owned by stow)
  108. # => q(existing link not owned by stow)
  109. #);
  110. ok(
  111. -l 'bin5' && readlink('bin5') eq '../not-stow'
  112. => q(existing link not owned by stow)
  113. );
  114. #
  115. # Target already exists, is owned by stow, but points to a different package
  116. #
  117. $stow = new_compat_Stow();
  118. make_path('bin6');
  119. make_path('../stow/pkg6a/bin6');
  120. make_file('../stow/pkg6a/bin6/file6');
  121. make_link('bin6/file6', '../../stow/pkg6a/bin6/file6');
  122. make_path('../stow/pkg6b/bin6');
  123. make_file('../stow/pkg6b/bin6/file6');
  124. $stow->plan_unstow('pkg6b');
  125. ok(
  126. $stow->get_conflict_count == 0 &&
  127. -l 'bin6/file6' &&
  128. readlink('bin6/file6') eq '../../stow/pkg6a/bin6/file6'
  129. => q(ignore existing link that points to a different package)
  130. );
  131. #
  132. # Don't unlink anything under the stow directory
  133. #
  134. make_path('stow'); # make out stow dir a subdir of target
  135. $stow = new_compat_Stow(dir => 'stow');
  136. # emulate stowing into ourself (bizarre corner case or accident)
  137. make_path('stow/pkg7a/stow/pkg7b');
  138. make_file('stow/pkg7a/stow/pkg7b/file7b');
  139. make_link('stow/pkg7b', '../stow/pkg7a/stow/pkg7b');
  140. capture_stderr();
  141. $stow->plan_unstow('pkg7b');
  142. is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg7b');
  143. ok(
  144. $stow->get_conflict_count == 0 &&
  145. -l 'stow/pkg7b' &&
  146. readlink('stow/pkg7b') eq '../stow/pkg7a/stow/pkg7b'
  147. => q(don't unlink any nodes under the stow directory)
  148. );
  149. like($stderr,
  150. qr/WARNING: skipping target which was current stow directory stow/
  151. => "warn when unstowing from ourself");
  152. uncapture_stderr();
  153. #
  154. # Don't unlink any nodes under another stow directory
  155. #
  156. $stow = new_compat_Stow(dir => 'stow');
  157. make_path('stow2'); # make our alternate stow dir a subdir of target
  158. make_file('stow2/.stow');
  159. # emulate stowing into ourself (bizarre corner case or accident)
  160. make_path('stow/pkg8a/stow2/pkg8b');
  161. make_file('stow/pkg8a/stow2/pkg8b/file8b');
  162. make_link('stow2/pkg8b', '../stow/pkg8a/stow2/pkg8b');
  163. capture_stderr();
  164. $stow->plan_unstow('pkg8a');
  165. is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg8a');
  166. ok(
  167. $stow->get_conflict_count == 0 &&
  168. -l 'stow2/pkg8b' &&
  169. readlink('stow2/pkg8b') eq '../stow/pkg8a/stow2/pkg8b'
  170. => q(don't unlink any nodes under another stow directory)
  171. );
  172. like($stderr,
  173. qr/WARNING: skipping target which was current stow directory stow/
  174. => "warn when skipping unstowing");
  175. uncapture_stderr();
  176. #
  177. # overriding already stowed documentation
  178. #
  179. # This will be used by this and subsequent tests
  180. sub check_protected_dirs_skipped {
  181. for my $dir (qw{stow stow2}) {
  182. like($stderr,
  183. qr/WARNING: skipping protected directory $dir/
  184. => "warn when skipping protected directory $dir");
  185. }
  186. uncapture_stderr();
  187. }
  188. $stow = new_compat_Stow(override => ['man9', 'info9']);
  189. make_file('stow/.stow');
  190. make_path('../stow/pkg9a/man9/man1');
  191. make_file('../stow/pkg9a/man9/man1/file9.1');
  192. make_path('man9/man1');
  193. make_link('man9/man1/file9.1' => '../../../stow/pkg9a/man9/man1/file9.1'); # emulate stow
  194. make_path('../stow/pkg9b/man9/man1');
  195. make_file('../stow/pkg9b/man9/man1/file9.1');
  196. capture_stderr();
  197. $stow->plan_unstow('pkg9b');
  198. $stow->process_tasks();
  199. ok(
  200. $stow->get_conflict_count == 0 &&
  201. !-l 'man9/man1/file9.1'
  202. => 'overriding existing documentation files'
  203. );
  204. check_protected_dirs_skipped();
  205. #
  206. # deferring to already stowed documentation
  207. #
  208. $stow = new_compat_Stow(defer => ['man10', 'info10']);
  209. make_path('../stow/pkg10a/man10/man1');
  210. make_file('../stow/pkg10a/man10/man1/file10a.1');
  211. make_path('man10/man1');
  212. make_link('man10/man1/file10a.1' => '../../../stow/pkg10a/man10/man1/file10a.1');
  213. # need this to block folding
  214. make_path('../stow/pkg10b/man10/man1');
  215. make_file('../stow/pkg10b/man10/man1/file10b.1');
  216. make_link('man10/man1/file10b.1' => '../../../stow/pkg10b/man10/man1/file10b.1');
  217. make_path('../stow/pkg10c/man10/man1');
  218. make_file('../stow/pkg10c/man10/man1/file10a.1');
  219. capture_stderr();
  220. $stow->plan_unstow('pkg10c');
  221. is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg10c');
  222. ok(
  223. $stow->get_conflict_count == 0 &&
  224. readlink('man10/man1/file10a.1') eq '../../../stow/pkg10a/man10/man1/file10a.1'
  225. => 'defer to existing documentation files'
  226. );
  227. check_protected_dirs_skipped();
  228. #
  229. # Ignore temp files
  230. #
  231. $stow = new_compat_Stow(ignore => ['~', '\.#.*']);
  232. make_path('../stow/pkg12/man12/man1');
  233. make_file('../stow/pkg12/man12/man1/file12.1');
  234. make_file('../stow/pkg12/man12/man1/file12.1~');
  235. make_file('../stow/pkg12/man12/man1/.#file12.1');
  236. make_path('man12/man1');
  237. make_link('man12/man1/file12.1' => '../../../stow/pkg12/man12/man1/file12.1');
  238. capture_stderr();
  239. $stow->plan_unstow('pkg12');
  240. $stow->process_tasks();
  241. ok(
  242. $stow->get_conflict_count == 0 &&
  243. !-e 'man12/man1/file12.1'
  244. => 'ignore temp files'
  245. );
  246. check_protected_dirs_skipped();
  247. #
  248. # Unstow an already unstowed package
  249. #
  250. $stow = new_compat_Stow();
  251. capture_stderr();
  252. $stow->plan_unstow('pkg12');
  253. is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12');
  254. ok(
  255. $stow->get_conflict_count == 0
  256. => 'unstow already unstowed package pkg12'
  257. );
  258. check_protected_dirs_skipped();
  259. #
  260. # Unstow a never stowed package
  261. #
  262. eval { remove_dir("$TEST_DIR/target"); };
  263. mkdir("$TEST_DIR/target");
  264. $stow = new_compat_Stow();
  265. capture_stderr();
  266. $stow->plan_unstow('pkg12');
  267. is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12 which was never stowed');
  268. ok(
  269. $stow->get_conflict_count == 0
  270. => 'unstow never stowed package pkg12'
  271. );
  272. check_protected_dirs_skipped();
  273. #
  274. # Unstowing when target contains a real file shouldn't be an issue.
  275. #
  276. make_file('man12/man1/file12.1');
  277. $stow = new_compat_Stow();
  278. capture_stderr();
  279. $stow->plan_unstow('pkg12');
  280. is($stow->get_tasks, 0, 'no tasks to process when unstowing pkg12 for third time');
  281. %conflicts = $stow->get_conflicts;
  282. ok(
  283. $stow->get_conflict_count == 1 &&
  284. $conflicts{unstow}{pkg12}[0]
  285. =~ m!existing target is neither a link nor a directory: man12/man1/file12\.1!
  286. => 'unstow pkg12 for third time'
  287. );
  288. check_protected_dirs_skipped();
  289. #
  290. # unstow a simple tree minimally when cwd isn't target
  291. #
  292. cd('../..');
  293. $stow = new_Stow(dir => "$TEST_DIR/stow", target => "$TEST_DIR/target");
  294. make_path("$TEST_DIR/stow/pkg13/bin13");
  295. make_file("$TEST_DIR/stow/pkg13/bin13/file13");
  296. make_link("$TEST_DIR/target/bin13", '../stow/pkg13/bin13');
  297. $stow->plan_unstow('pkg13');
  298. $stow->process_tasks();
  299. ok(
  300. $stow->get_conflict_count == 0 &&
  301. -f "$TEST_DIR/stow/pkg13/bin13/file13" && ! -e "$TEST_DIR/target/bin13"
  302. => 'unstow a simple tree'
  303. );
  304. #
  305. # unstow a simple tree minimally with absolute stow dir when cwd isn't
  306. # target
  307. #
  308. $stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
  309. target => "$TEST_DIR/target");
  310. make_path("$TEST_DIR/stow/pkg14/bin14");
  311. make_file("$TEST_DIR/stow/pkg14/bin14/file14");
  312. make_link("$TEST_DIR/target/bin14", '../stow/pkg14/bin14');
  313. $stow->plan_unstow('pkg14');
  314. $stow->process_tasks();
  315. ok(
  316. $stow->get_conflict_count == 0 &&
  317. -f "$TEST_DIR/stow/pkg14/bin14/file14" && ! -e "$TEST_DIR/target/bin14"
  318. => 'unstow a simple tree with absolute stow dir'
  319. );
  320. #
  321. # unstow a simple tree minimally with absolute stow AND target dirs
  322. # when cwd isn't target
  323. #
  324. $stow = new_Stow(dir => canon_path("$TEST_DIR/stow"),
  325. target => canon_path("$TEST_DIR/target"));
  326. make_path("$TEST_DIR/stow/pkg15/bin15");
  327. make_file("$TEST_DIR/stow/pkg15/bin15/file15");
  328. make_link("$TEST_DIR/target/bin15", '../stow/pkg15/bin15');
  329. $stow->plan_unstow('pkg15');
  330. $stow->process_tasks();
  331. ok(
  332. $stow->get_conflict_count == 0 &&
  333. -f "$TEST_DIR/stow/pkg15/bin15/file15" && ! -e "$TEST_DIR/target/bin15"
  334. => 'unstow a simple tree with absolute stow and target dirs'
  335. );
  336. # Todo
  337. #
  338. # Test cleaning up subdirs with --paranoid option