Skip to content

Commit

Permalink
sh: relax skip_hardlink check
Browse files Browse the repository at this point in the history
Apparently when --merge-directories is enabled, and --rank-by is not
sufficient to pick a specific original file in a group, the head
hardlink and the original file may not be the same. Relax the check in
rm_sh_emit_handler_hardlink to just compare the inode (the device is
already known to be the same).

Fixes #545
  • Loading branch information
cebtenzzre committed Jun 20, 2023
1 parent b76f853 commit b2e06a6
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 13 deletions.
2 changes: 1 addition & 1 deletion lib/formats/sh.c.in
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ static bool rm_sh_emit_handler_hardlink(RmFmtHandlerShScript *self, char **out,
return false;
}

if (self->last_original && RM_FILE_HARDLINK_HEAD(file) == self->last_original) {
if (self->last_original && self->last_original->inode == file->inode) {
*out = g_strdup_printf("skip_hardlink '%s' '%s'", dupe_escaped, orig_escaped);
} else {
*out = g_strdup_printf("cp_hardlink '%s' '%s'", dupe_escaped, orig_escaped);
Expand Down
27 changes: 25 additions & 2 deletions tests/test_formatters/test_sh.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#!/usr/bin/env python3
# encoding: utf-8
from nose import with_setup
from tests.utils import *

import shlex
import subprocess

from nose import with_setup
from parameterized import parameterized
from tests.utils import *


def run_shell_script(shell, sh_path, *args):
Expand Down Expand Up @@ -291,3 +292,25 @@ def test_keep_parent_timestamps(shell):
stat_after = os.stat(dir_path)

assert stat_before.st_mtime == stat_after.st_mtime


# regression test for GitHub issue #545
@parameterized.expand([('',), ('-D',)])
@with_setup(usual_setup_func, usual_teardown_func)
def test_skip_hardlinks(tm_opt):
dir_a = create_dirs('a')
create_file('xxx', 'a/1')
create_file('yyy', 'a/2')
dir_b = create_dirs('b')
create_link('a/2', 'b/2')

sh_path = os.path.join(TESTDIR_NAME, 'rmlint.sh')
run_rmlint(
'-S a -o sh:{p} -c sh:hardlink'.format(p=shlex.quote(sh_path)),
tm_opt, dir_a, dir_b,
use_default_dir=False,
)

counts = pattern_count(sh_path, ["^cp_hardlink +'", "^skip_hardlink +'"])
assert counts[0] == 0
assert counts[1] == 1
10 changes: 0 additions & 10 deletions tests/test_mains/test_dedupe.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,6 @@ def test_dedupe_works():
verbosity=""
)

# count the number of line in a file which start with patterns[]
def pattern_count(path, patterns):
counts = [0] * len(patterns)
with open(path, 'r') as f:
for line in f:
for i, pattern in enumerate(patterns):
if re.match(pattern, line):
counts[i] += 1
return counts


@needs_reflink_fs
@with_setup(usual_setup_func, usual_teardown_func)
Expand Down
12 changes: 12 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import time
import pprint
import psutil
import re
import shutil
import shlex
import struct
Expand Down Expand Up @@ -468,3 +469,14 @@ def not_reflink_fs(*args):
return make_decorator(test)(not_reflink_fs)
else:
return test


# count the number of line in a file which start with each pattern
def pattern_count(path, patterns):
counts = [0] * len(patterns)
with open(path, 'r') as f:
for line in f:
for i, pattern in enumerate(patterns):
if re.match(pattern, line):
counts[i] += 1
return counts

0 comments on commit b2e06a6

Please sign in to comment.