Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package jdupes for openSUSE:Factory checked 
in at 2022-03-22 19:39:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/jdupes (Old)
 and      /work/SRC/openSUSE:Factory/.jdupes.new.25692 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "jdupes"

Tue Mar 22 19:39:49 2022 rev:2 rq:963793 version:1.20.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/jdupes/jdupes.changes    2022-03-11 
21:41:45.566093318 +0100
+++ /work/SRC/openSUSE:Factory/.jdupes.new.25692/jdupes.changes 2022-03-22 
19:39:51.799068706 +0100
@@ -1,0 +2,7 @@
+Mon Mar 14 22:06:26 UTC 2022 - Dirk M??ller <dmuel...@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 
+
+-------------------------------------------------------------------

New:
----
  jdupes_wrapper.cpp

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ jdupes.spec ++++++
--- /var/tmp/diff_new_pack.fRm28S/_old  2022-03-22 19:39:52.323069255 +0100
+++ /var/tmp/diff_new_pack.fRm28S/_new  2022-03-22 19:39:52.327069260 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package jdupes
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 # Copyright (c) 2019-2020 Malcolm J Lewis <malcolmle...@opensuse.org>
 #
 # All modifications and additions to the file contributed by third parties
@@ -26,6 +26,8 @@
 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.
@@ -41,11 +43,13 @@
 %build
 make %{?_smp_mflags} \
      ENABLE_DEDUPE=1 \
-     STATIC_DEDUPE_H=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
@@ -56,5 +60,6 @@
 %{_bindir}/%{name}
 %{_mandir}/man1/%{name}.1%{?ext_man}
 %{_rpmmacrodir}/macros.%{name}
+/usr/lib/rpm/jdupes_wrapper
 
 %changelog

++++++ jdupes_wrapper.cpp ++++++
/*
 * A little helper to wrap around jdupes and create hard/soft links of the
 * dups found. Used in openSUSE rpm.
 *
 * Copyright 2022 Jiri Slaby <jsl...@suse.cz>
 *           2022 Stephan Kulow <co...@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;
}

++++++ macros.jdupes ++++++
--- /var/tmp/diff_new_pack.fRm28S/_old  2022-03-22 19:39:52.371069306 +0100
+++ /var/tmp/diff_new_pack.fRm28S/_new  2022-03-22 19:39:52.375069310 +0100
@@ -1,21 +1,5 @@
-%jdupes(s) \
- _target=""; _symlinks=0; \
- %{-s:_symlinks=1;} \
- if test "$_symlinks" = 1; then \
-   jdupes -q -p -H -o name -r %1 | \
-   while read _file; do \
-     if test -z "$_target" ; then \
-       _target="$_file"; \
-     else \
-       if test -z "$_file" ; then \
-         _target=""; \
-         continue ; \
-       fi ; \
-       ln -sf "${_target#%{buildroot}}" "$_file"; \
-     fi ; \
-   done ; \
- else \
-   jdupes -q -p -H -o name -L -r %1 ; \
- fi ; \
-%{nil}
+%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}
 

Reply via email to