Sync from SUSE:SLFO:Main jdupes revision bb00d6ff97e806ab31527afd6bf010e9
This commit is contained in:
commit
01ccc9dca9
23
.gitattributes
vendored
Normal file
23
.gitattributes
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
## Default LFS
|
||||
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||
*.bsp filter=lfs diff=lfs merge=lfs -text
|
||||
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.gem filter=lfs diff=lfs merge=lfs -text
|
||||
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||
*.jar filter=lfs diff=lfs merge=lfs -text
|
||||
*.lz filter=lfs diff=lfs merge=lfs -text
|
||||
*.lzma filter=lfs diff=lfs merge=lfs -text
|
||||
*.obscpio filter=lfs diff=lfs merge=lfs -text
|
||||
*.oxt filter=lfs diff=lfs merge=lfs -text
|
||||
*.pdf filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.rpm filter=lfs diff=lfs merge=lfs -text
|
||||
*.tbz filter=lfs diff=lfs merge=lfs -text
|
||||
*.tbz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||
*.txz filter=lfs diff=lfs merge=lfs -text
|
||||
*.whl filter=lfs diff=lfs merge=lfs -text
|
||||
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.zst filter=lfs diff=lfs merge=lfs -text
|
153
jdupes.changes
Normal file
153
jdupes.changes
Normal file
@ -0,0 +1,153 @@
|
||||
-------------------------------------------------------------------
|
||||
Thu Feb 9 17:13:54 UTC 2023 - Dirk Müller <dmueller@suse.com>
|
||||
|
||||
- update to 1.21.3:
|
||||
* Major performance fix in the double traversal prevention tree
|
||||
code
|
||||
* Added undocumented '-9' benchmark option for testing traversal
|
||||
code
|
||||
* Extra error checks to try to finally solve a very rare crash
|
||||
bug
|
||||
* Tiny code size reduction by discarding unused xxHash code
|
||||
* jody_hash re-added as a build-time option
|
||||
* Many options/features/safety checks can now be selectively
|
||||
compiled out
|
||||
* New 'make BARE_BONES=1' option builds the most minimal jdupes
|
||||
possible
|
||||
* Fix exit behavior when no valid directories are given
|
||||
* Only act on "normal" files and directories
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Dec 6 21:35:51 UTC 2022 - Dirk Müller <dmueller@suse.com>
|
||||
|
||||
- update to 1.21.1:
|
||||
* Reinstate '-I/--isolate' by popular demand; use at your own risk!
|
||||
* Expect to lose data if you use this feature. It is strongly susceptible
|
||||
to the documented "triangle problem" and absolutely does not protect
|
||||
files in each directory from matching with one another. Don't get mad at
|
||||
me if you use it and see a cloud of smoke come out of your disk array.
|
||||
* Remove '-I/--isolate' which has never worked correctly
|
||||
* Fix compiling when NO_HARDLINKS and NO_SYMLINKS are both defined
|
||||
* Increased stack size limits to enable deeper recursion without crashing
|
||||
* Fixes to make compilation under Cygwin (instead of MSYS2 MinGW) work
|
||||
* Remove the temporary '-X help' warning about changes in functionality
|
||||
* Some minor under-the-hood changes for future enhancements
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Mar 14 22:06:26 UTC 2022 - Dirk Müller <dmueller@suse.com>
|
||||
|
||||
- add jdupes_wrapper to speedup symlinks
|
||||
- add new %suse_symlink_dupes and %suse_hardlink_dupes macros
|
||||
which are more descriptive than a %jdupes or %fdupes
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Mar 9 21:54:15 UTC 2022 - Dirk Müller <dmueller@suse.com>
|
||||
|
||||
- update to 1.20.2:
|
||||
* Interactive deletion now offers "link set" options too
|
||||
* Interactive deletion now assumes 'a' when you just hit [ENTER]
|
||||
- add jdupes rpm macro for dropin %%fdupes replacement
|
||||
- run tests
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Jul 08 20:24:03 UTC 2021 - idesmi@protonmail.com
|
||||
|
||||
- Update to version 1.20.0:
|
||||
* v1.20.0 release
|
||||
* Update copyright years and financial support information
|
||||
* Update README.md and manpage: long options and copyright years
|
||||
* jody_*: update/add copyright information
|
||||
* oom.c/h: change license to Creative Commons 0 (public domain)
|
||||
* stupid_dupes.sh: update version information and copyright years
|
||||
* Use consistent hyphenation in long options; remove deprecated -n
|
||||
* Remove redundant warning about another option (#172)
|
||||
* Fix -P partial printout when progress indicator is enabled
|
||||
* INSTALL: More stern warnings to not use LOW_MEMORY inappropriately
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Sun Nov 1 23:22:39 UTC 2020 - malcolmlewis@opensuse.org
|
||||
|
||||
- Updated to version 1.19.0:
|
||||
* Make -X size[+-=] an inclusion filter instead (CHECK YOUR SHELL
|
||||
SCRIPTS).
|
||||
* Fix -X noext/only extension matching bugs.
|
||||
* Remove deprecated -x/--xsize option and some undocumented
|
||||
redundant options.
|
||||
* Name sorting is now case-insensitive.
|
||||
* Disable -K/--skiphash which was accidentally left active but
|
||||
doesn't work.
|
||||
* When sorting by modify time and there's a tie, break it using
|
||||
name sorting.
|
||||
* jdupes-standalone has been removed due to falling too far out
|
||||
of sync.
|
||||
* Embedded build date option has been removed.
|
||||
- Changes from version 1.18.2:
|
||||
* Add -U/--notravcheck to skip double-traversal safety (for
|
||||
Google Drive FS).
|
||||
- Changes from version 1.18.0
|
||||
* Add -X newer/older extfilters to reject files by modification
|
||||
date.
|
||||
- Changes from version 1.17.0:
|
||||
* Rewrite dedupe code from scratch, probably fixing all dedupe
|
||||
bugs.
|
||||
* extfilter: add substring match filter for file paths.
|
||||
* Add -u/--printunique option to print all non-duplicates
|
||||
(unmatched files).
|
||||
* Dedupe-blacklisted kernel version check now happens before
|
||||
work is done.
|
||||
- Changes from version 1.16.0:
|
||||
* Add -X noext/onlyext filters to exclude/require specific file
|
||||
extension(s).
|
||||
* Added in-depth help text for -X/--extfilter (use -X help to
|
||||
view).
|
||||
* This version still has BTRFS dedupe issues and file add-by-name
|
||||
disabled.
|
||||
- Changes from version 1.15.0:
|
||||
* Disable single file addition on the command line for safety.
|
||||
- CHanges from version 1.14.1:
|
||||
* Fix some compilation issues.
|
||||
* Add example shell scripts for processing piped jdupes output.
|
||||
* Fix some swapped/mangled help text in program and
|
||||
documentation.
|
||||
*LOW_MEMORY compiles exclude more stuff to further reduce usage.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Mar 19 03:27:55 UTC 2020 - malcolmlewis@opensuse.org
|
||||
|
||||
- Updated to version 1.14.0
|
||||
* Long option --exclude is deprecated and renamed --extfilter.
|
||||
* BTRFS compile options have been generalized to dedupe,
|
||||
(see README).
|
||||
* Fix a bug in 1.13.3 where many options caused an inappropriate
|
||||
exit.
|
||||
- Changes from version 1.13.3:
|
||||
* Fix the behavior of the -I/--isolate option.
|
||||
* Move BTRFS-specific dedupe interfaces to general Linux 4.5+
|
||||
interfaces.
|
||||
* Change BTRFS compilation flag name (see README).
|
||||
* Fix FS dedupe only working on the first 16 MiB of files.
|
||||
* Add FS dedupe static header for when this header is missing.
|
||||
* Correct several copyright dates and comments.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Aug 6 20:02:38 UTC 2019 - malcolmlewis@opensuse.org
|
||||
|
||||
- Updated to version 1.13.2:
|
||||
* Fix Unicode and escapes in JSON output,
|
||||
(gh#jbruchon/jdupes#109).
|
||||
|
||||
------------------------------------------------------------------
|
||||
Sun Jul 14 23:44:59 UTC 2019 - malcolmlewis@opensuse.org
|
||||
|
||||
- Updated to version 1.13.1:
|
||||
* Fix an incorrect NULL pointer check.
|
||||
- Changes from version 1.13:
|
||||
* Add new option -j/--json for JSON (machine-readable) output.
|
||||
* /usr/local is now the default PREFIX in Makefile.
|
||||
* Minor performance optimizations.
|
||||
* A few minor bug fixes.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Sun Apr 28 04:35:40 UTC 2019 - malcolmlewis@opensuse.org
|
||||
|
||||
- Initial build.
|
65
jdupes.spec
Normal file
65
jdupes.spec
Normal file
@ -0,0 +1,65 @@
|
||||
#
|
||||
# spec file for package jdupes
|
||||
#
|
||||
# Copyright (c) 2023 SUSE LLC
|
||||
# Copyright (c) 2019-2020 Malcolm J Lewis <malcolmlewis@opensuse.org>
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
# upon. The license for this file, and modifications and additions to the
|
||||
# file, is the same license as for the pristine package itself (unless the
|
||||
# license for the pristine package is not an Open Source License, in which
|
||||
# case the license is the MIT License). An "Open Source License" is a
|
||||
# license that conforms to the Open Source Definition (Version 1.9)
|
||||
# published by the Open Source Initiative.
|
||||
|
||||
# Please submit bugfixes or comments via https://bugs.opensuse.org/
|
||||
#
|
||||
|
||||
|
||||
Name: jdupes
|
||||
Version: 1.21.3
|
||||
Release: 0
|
||||
Summary: A powerful duplicate file finder and an enhanced fork of 'fdupes'
|
||||
License: MIT
|
||||
Group: Productivity/File utilities
|
||||
URL: https://github.com/jbruchon/jdupes
|
||||
Source0: https://github.com/jbruchon/jdupes/archive/refs/tags/v%{version}.tar.gz
|
||||
Source1: macros.jdupes
|
||||
Source2: jdupes_wrapper.cpp
|
||||
BuildRequires: gcc-c++
|
||||
|
||||
%description
|
||||
A program for identifying and taking actions upon duplicate files.
|
||||
|
||||
A WORD OF WARNING: jdupes IS NOT a drop-in compatible replacement for fdupes!
|
||||
Do not blindly replace fdupes with jdupes in scripts and expect everything to
|
||||
work the same way. Option availability and meanings differ between the two
|
||||
programs.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
make %{?_smp_mflags} \
|
||||
ENABLE_DEDUPE=1 \
|
||||
STATIC_DEDUPE_H=1
|
||||
g++ %{optflags} -O2 -Wall %{SOURCE2} -o jdupes_wrapper
|
||||
|
||||
%install
|
||||
make DESTDIR=%{buildroot} PREFIX=%{_prefix} install
|
||||
install -D -m644 %{SOURCE1} %{buildroot}%{_rpmmacrodir}/macros.%{name}
|
||||
install -D -m755 jdupes_wrapper %{buildroot}/usr/lib/rpm/jdupes_wrapper
|
||||
|
||||
%check
|
||||
./jdupes -q -r testdir
|
||||
|
||||
%files
|
||||
%license LICENSE
|
||||
%doc CHANGES README.md
|
||||
%{_bindir}/%{name}
|
||||
%{_mandir}/man1/%{name}.1%{?ext_man}
|
||||
%{_rpmmacrodir}/macros.%{name}
|
||||
/usr/lib/rpm/jdupes_wrapper
|
||||
|
||||
%changelog
|
167
jdupes_wrapper.cpp
Normal file
167
jdupes_wrapper.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* A little helper to wrap around jdupes and create hard/soft links of the
|
||||
* dups found. Used in openSUSE rpm.
|
||||
*
|
||||
* Copyright 2022 Jiri Slaby <jslaby@suse.cz>
|
||||
* 2022 Stephan Kulow <coolo@suse.de>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <tuple>
|
||||
#include <unistd.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
typedef std::map<ino_t, std::vector<std::string>> dups_map;
|
||||
typedef std::pair<ino_t, size_t> nlink_pair;
|
||||
|
||||
bool cmp_nlink(const nlink_pair& a, const nlink_pair& b)
|
||||
{
|
||||
return a.second > b.second;
|
||||
}
|
||||
|
||||
void sort_by_count(const dups_map& in, std::vector<ino_t>& out)
|
||||
{
|
||||
out.clear();
|
||||
std::list<nlink_pair> nlinks;
|
||||
for (auto it = in.cbegin(); it != in.cend(); ++it) {
|
||||
nlinks.push_back(std::make_pair(it->first, it->second.size()));
|
||||
}
|
||||
nlinks.sort(cmp_nlink);
|
||||
for (auto it = nlinks.cbegin(); it != nlinks.cend(); ++it) {
|
||||
out.push_back(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void link_file(const std::string& file, const std::string& target, bool symlink)
|
||||
{
|
||||
std::cout << "Linking " << file << " -> " << target << std::endl;
|
||||
if (unlink(file.c_str())) {
|
||||
std::cerr << "Removing '" << file << "' failed." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
int ret;
|
||||
if (symlink) {
|
||||
ret = ::symlink(target.c_str(), file.c_str());
|
||||
} else {
|
||||
ret = link(target.c_str(), file.c_str());
|
||||
}
|
||||
if (ret) {
|
||||
std::cerr << "Linking '" << file << "' failed." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_dups(const dups_map& dups, const std::string& buildroot, bool symlink)
|
||||
{
|
||||
// all are hardlinks to the same data
|
||||
if (dups.size() < 2)
|
||||
return;
|
||||
std::vector<ino_t> sorted;
|
||||
sort_by_count(dups, sorted);
|
||||
auto inodes = sorted.begin();
|
||||
std::string target = dups.at(*inodes).front();
|
||||
if (symlink) {
|
||||
target.replace(0, buildroot.length(), "");
|
||||
}
|
||||
|
||||
for (++inodes; inodes != sorted.end(); ++inodes) {
|
||||
const std::vector<std::string> files = dups.at(*inodes);
|
||||
for (auto it = files.begin(); it != files.end(); ++it) {
|
||||
link_file(*it, target, symlink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
bool symlink = false;
|
||||
std::string root;
|
||||
std::string buildroot;
|
||||
while (1) {
|
||||
int result = getopt(argc, argv, "sb:");
|
||||
if (result == -1)
|
||||
break; /* end of list */
|
||||
switch (result) {
|
||||
case 's':
|
||||
symlink = true;
|
||||
break;
|
||||
case 'b':
|
||||
buildroot = optarg;
|
||||
break;
|
||||
default: /* unknown */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buildroot.empty()) {
|
||||
if (symlink) {
|
||||
std::cerr << "Missing -b argument to remove bootroot from symlink targets";
|
||||
return 1;
|
||||
}
|
||||
// eliminate final slash from directory argument
|
||||
if (buildroot.back() == '/') {
|
||||
buildroot.pop_back();
|
||||
}
|
||||
}
|
||||
if (optind < argc) {
|
||||
root = argv[optind++];
|
||||
} else {
|
||||
std::cerr << "Missing directory argument.";
|
||||
}
|
||||
if (optind < argc) {
|
||||
std::cerr << "Too many arguments.";
|
||||
return 1;
|
||||
}
|
||||
/* jdupes options used:
|
||||
-q: hide progress indicator
|
||||
-p: don't consider files with different owner/group or permission bits as duplicates
|
||||
-o name: output order of duplicates
|
||||
-r: follow subdirectories
|
||||
-H: also report hard links as duplicates
|
||||
*/
|
||||
std::string command = "jdupes -q -p -o name";
|
||||
if (!symlink) {
|
||||
/* if we create symlinks, avoid looking at hard links being duplicated. This way
|
||||
jdupes is faster and won't break them up anyway */
|
||||
command += " -H";
|
||||
}
|
||||
command += " -r '" + root + "'";
|
||||
FILE* pipe = popen(command.c_str(), "r");
|
||||
if (!pipe) {
|
||||
throw std::runtime_error("popen() failed!");
|
||||
}
|
||||
std::array<char, MAXPATHLEN> buffer;
|
||||
dups_map dups;
|
||||
while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) {
|
||||
std::string line = buffer.data();
|
||||
if (line.length() < 2) {
|
||||
handle_dups(dups, buildroot, symlink);
|
||||
dups.clear();
|
||||
continue;
|
||||
}
|
||||
if (line.back() != '\n') {
|
||||
std::cerr << "Too long lines? '" << line << "'" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
line.pop_back();
|
||||
|
||||
struct stat sb;
|
||||
if (stat(line.c_str(), &sb)) {
|
||||
std::cerr << "Stat on '" << buffer.data() << "' failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
dups[sb.st_ino].push_back(line);
|
||||
}
|
||||
pclose(pipe);
|
||||
|
||||
return 0;
|
||||
}
|
4
macros.jdupes
Normal file
4
macros.jdupes
Normal file
@ -0,0 +1,4 @@
|
||||
%suse_symlink_dupes /usr/lib/rpm/jdupes_wrapper -b %{buildroot} -s
|
||||
%suse_hardlink_dupes jdupes -q -p -H -o name -L -r %1
|
||||
|
||||
%fdupes /usr/lib/rpm/jdupes_wrapper -b %{buildroot}
|
BIN
v1.21.3.tar.gz
(Stored with Git LFS)
Normal file
BIN
v1.21.3.tar.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user