Bug#1120799: Using python-apt's apt_pkg with a chroot

2025-12-02 Thread Sebastiaan Couwenberg

On 12/3/25 7:52 AM, Sebastiaan Couwenberg wrote:

The config dump for Perl AptPkg shows a mix of the system apt.conf and the 
config set in the code, the config dump for python-apt shows only the config 
set in the code.


That's because apt_pkg.config needs to be used instead of another 
apt_pkg.Configuration instance:

 
https://salsa.debian.org/sebastic/release.debian.org/-/commit/d7428cd396313d20773d0f10331623f1e2cb2ff6

Now both the Perl & Python scripts work as expected with the chroot & chdist:

 # Python with chroot
 $ unshare --map-auto --map-user=65536 --map-group=65536 --keep-caps -- 
~/git/release-team/release.debian.org/bin/resolve-dependencies.py -vdp opencv
 Resolving dependencies for: opencv
 Chroot already exists: /var/tmp/testing-chroot
 config:
 [...]
 Dir "/";
 [...]
 RootDir "/var/tmp/testing-chroot";
 
 list:

 [https://deb.debian.org/debian/' 
dist='testing' is_trusted='1'>]
 Reading package lists... Done
 Building dependency tree... Done
 Reading state information... Done
 Package: opencv
 Version: 4.10.0+dfsg-6
 [...]


 # Python with chdist
 $ ~/git/release-team/release.debian.org/bin/resolve-dependencies.py -vdp 
opencv -D
 Resolving dependencies for: opencv
 config:
 [...]
 Dir "/var/tmp/testing-chdist";
 [...]
 
 list:

 [https://deb.debian.org/debian/' 
dist='testing' is_trusted='1'>]
 Reading package lists... Done
 Building dependency tree... Done
 Package: opencv
 Version: 4.10.0+dfsg-6
 [...]


 # Perl with chroot
 $ unshare --map-auto --map-user=65536 --map-group=65536 --keep-caps -- 
~/git/release-team/release.debian.org/bin/resolve-dependencies.pl -vdp opencv
 config:
 [...]
 Dir "/";
 [...]
 RootDir "/var/tmp/testing-chroot";
 Getting source package: opencv
 Package: opencv
 Version: 4.10.0+dfsg-6
 Source:  
https://deb.debian.org/debian/pool/main/o/opencv/opencv_4.10.0%2bdfsg-6.dsc


 # Perl with chdist
 $ ~/git/release-team/release.debian.org/bin/resolve-dependencies.pl -vdp 
opencv -D
 config:
 [..]
 Dir "/var/tmp/testing-chdist";
 [...]
 Getting source package: opencv
 Package: opencv
 Version: 4.10.0+dfsg-6
 Source:  
https://deb.debian.org/debian/pool/main/o/opencv/opencv_4.10.0%2bdfsg-6.dsc


Kind Regards,

Bas

--
 PGP Key ID: 4096R/6750F10AE88D4AF1
Fingerprint: 8182 DE41 7056 408D 6146  50D1 6750 F10A E88D 4AF1



Bug#1120799: Using python-apt's apt_pkg with a chroot

2025-12-02 Thread Sebastiaan Couwenberg

On 12/2/25 7:44 PM, Sebastiaan Couwenberg wrote:

On 12/2/25 7:17 PM, Johannes Schauer Marin Rodrigues wrote:

Quoting Sebastiaan Couwenberg (2025-12-02 18:36:00)

Using python-apt's apt_pkg with a chroot turns out to be non-trivial unlike 
apt.cache.

I'm running a script [0] on a trixie system and need to interact with the cache 
in a testing chroot.

The chroot is created with mmdebstrap --mode=unshare, and the script is run via 
unshare as well.


maybe this is an XY problem.

Why do you need a full chroot for something that is as far as I get from the
script just a "I want apt to resolve the dependencies with my custom
sources.list"? This sounds like something like chdist is doing?


I want to use apt to resolve dependencies for packages (both source & binary) 
in testing (and unstable), but the code won't be running on a testing (or unstable) 
system.

See #1120799 for context.


Maybe the mmdebstrap man page has an example which helps you. It is a snippet
which is the very bare-bones of what mmdebstrap does with a few thousand more
lines of code:

 mkdir -p "$2/etc/apt" "$2/var/cache" "$2/var/lib"
 cat << END > "$2/apt.conf"
 Apt::Architecture "$(dpkg --print-architecture)";
 Apt::Architectures "$(dpkg --print-architecture)";
 Dir "$(cd "$2" && pwd)";
 Dir::Etc::Trusted "$(eval "$(apt-config shell v Dir::Etc::Trusted/f)"; printf %s 
"$v")";
 Dir::Etc::TrustedParts "$(eval "$(apt-config shell v Dir::Etc::TrustedParts/d)"; 
printf %s "$v"

 END
 echo "deb http://deb.debian.org/debian/ $1 main" > 
"$2/etc/apt/sources.list"
 APT_CONFIG="$2/apt.conf" apt-get update
 APT_CONFIG="$2/apt.conf" apt-get --yes --download-only install '?essential'
 for f in "$2"/var/cache/apt/archives/*.deb; do dpkg-deb --extract "$f" 
"$2"; done
 chroot "$2" sh -c "dpkg --install --force-depends 
/var/cache/apt/archives/*.deb"


How would python-apt's apt_pkg use this?


Setting RootDir in the config does not result in the chroot paths to be used:


I think you need Dir.


Not according to the apt.conf(5):

"
   The configuration item RootDir has a special meaning. If set, all paths will 
be relative to RootDir, even paths that are specified absolutely. So, for 
instance, if RootDir is set to /tmp/staging and Dir::State::status is set to 
/var/lib/dpkg/status, then the status file will be looked up in 
/tmp/staging/var/lib/dpkg/status. If you want to prefix only relative paths, 
set Dir instead.
"

Using Dir fails in the same way:

  [...]


python-apt fails to use the chdist the same way it fails to use the chroot, 
Perl AptPkg uses both as expected.

You can reproduce this with the scripts from my transition-autopkgtest branch:

 
https://salsa.debian.org/sebastic/release.debian.org/-/commit/1d872c5a1d30ce5bea2064de75747ea4b6f0e73b

Perl AptPkg initializes the system via the config:

 $_config->init;
 if ($cfg{use_chdist}) {
 $_config->set('Dir', $cfg{chdist_path});
 }
 else {
 $_config->set('RootDir', $cfg{chroot_path});
 }
 $_system = $_config->system;

Whereas python-apt initializes them separately:

 apt_pkg.init_config()
 apt_pkg.init_system()

 config = apt_pkg.Configuration()
 if args.use_chdist:
 config.set('Dir', args.chdist_path)
 else:
 config.set('RootDir', args.chroot_path)

The modified config is not used by the python-apt classes.

The config dump for Perl AptPkg shows a mix of the system apt.conf and the 
config set in the code, the config dump for python-apt shows only the config 
set in the code.

Kind Regards,

Bas

--
 PGP Key ID: 4096R/6750F10AE88D4AF1
Fingerprint: 8182 DE41 7056 408D 6146  50D1 6750 F10A E88D 4AF1



Bug#1120799: Using python-apt's apt_pkg with a chroot

2025-12-02 Thread Sebastiaan Couwenberg

On 12/2/25 6:36 PM, Sebastiaan Couwenberg wrote:

Using python-apt's apt_pkg with a chroot turns out to be non-trivial unlike 
apt.cache.

I'm running a script [0] on a trixie system and need to interact with the cache 
in a testing chroot.

The chroot is created with mmdebstrap --mode=unshare, and the script is run via 
unshare as well.

Setting RootDir in the config does not result in the chroot paths to be used:


This seems to be an issue with python-apts apt_pkg, because Perl AptPkg works 
as expected:

 $ unshare --map-auto --map-user=65536 --map-group=65536 --keep-caps -- 
~/git/release-team/release.debian.org/bin/resolve-dependencies.pl
 Package: opencv
 Version: 4.10.0+dfsg-6
 Source:  
https://deb.debian.org/debian/pool/main/o/opencv/opencv_4.10.0%2bdfsg-6.dsc

This Perl script [1] is getting the data for testing by using the chroot.

[1] 
https://salsa.debian.org/sebastic/release.debian.org/-/blob/a6708dcc8e00ce1e16b1cd94909890e8098ea2f5/bin/resolve-dependencies.pl

Kind Regards,

Bas

--
 PGP Key ID: 4096R/6750F10AE88D4AF1
Fingerprint: 8182 DE41 7056 408D 6146  50D1 6750 F10A E88D 4AF1



Bug#1120799: Using python-apt's apt_pkg with a chroot

2025-12-02 Thread Sebastiaan Couwenberg

On 12/2/25 7:17 PM, Johannes Schauer Marin Rodrigues wrote:

Quoting Sebastiaan Couwenberg (2025-12-02 18:36:00)

Using python-apt's apt_pkg with a chroot turns out to be non-trivial unlike 
apt.cache.

I'm running a script [0] on a trixie system and need to interact with the cache 
in a testing chroot.

The chroot is created with mmdebstrap --mode=unshare, and the script is run via 
unshare as well.


maybe this is an XY problem.

Why do you need a full chroot for something that is as far as I get from the
script just a "I want apt to resolve the dependencies with my custom
sources.list"? This sounds like something like chdist is doing?


I want to use apt to resolve dependencies for packages (both source & binary) 
in testing (and unstable), but the code won't be running on a testing (or unstable) 
system.

See #1120799 for context.


Maybe the mmdebstrap man page has an example which helps you. It is a snippet
which is the very bare-bones of what mmdebstrap does with a few thousand more
lines of code:

 mkdir -p "$2/etc/apt" "$2/var/cache" "$2/var/lib"
 cat << END > "$2/apt.conf"
 Apt::Architecture "$(dpkg --print-architecture)";
 Apt::Architectures "$(dpkg --print-architecture)";
 Dir "$(cd "$2" && pwd)";
 Dir::Etc::Trusted "$(eval "$(apt-config shell v Dir::Etc::Trusted/f)"; printf %s 
"$v")";
 Dir::Etc::TrustedParts "$(eval "$(apt-config shell v Dir::Etc::TrustedParts/d)"; 
printf %s "$v"

 END
 echo "deb http://deb.debian.org/debian/ $1 main" > 
"$2/etc/apt/sources.list"
 APT_CONFIG="$2/apt.conf" apt-get update
 APT_CONFIG="$2/apt.conf" apt-get --yes --download-only install '?essential'
 for f in "$2"/var/cache/apt/archives/*.deb; do dpkg-deb --extract "$f" 
"$2"; done
 chroot "$2" sh -c "dpkg --install --force-depends 
/var/cache/apt/archives/*.deb"


How would python-apt's apt_pkg use this?


Setting RootDir in the config does not result in the chroot paths to be used:


I think you need Dir.


Not according to the apt.conf(5):

"
  The configuration item RootDir has a special meaning. If set, all paths will 
be relative to RootDir, even paths that are specified absolutely. So, for 
instance, if RootDir is set to /tmp/staging and Dir::State::status is set to 
/var/lib/dpkg/status, then the status file will be looked up in 
/tmp/staging/var/lib/dpkg/status. If you want to prefix only relative paths, 
set Dir instead.
"

Using Dir fails in the same way:

 $ unshare --map-auto --map-user=65536 --map-group=65536 --keep-caps -- 
~/git/release-team/release.debian.org/bin/resolve-dependencies.py -vdp opencv -u 
2>&1 | tee /tmp/resolve-dependencies.log
 Resolving dependencies for: opencv
 Chroot already exists: /var/tmp/testing-chroot
 config:
 Dir "/var/tmp/testing-chroot";

 list:
 [http://ftp.nl.debian.org/debian/' 
dist='trixie' is_trusted='1'>,
  http://ftp.nl.debian.org/debian/' 
dist='trixie-updates' is_trusted='1'>,
  http://security.debian.org/debian-security/' dist='trixie-security' 
is_trusted='1'>,
  http://ftp.nl.debian.org/debian/' 
dist='trixie-backports' is_trusted='1'>,
  http://debug.mirrors.debian.org/debian-debug/' dist='trixie-debug' 
is_trusted='1'>]
 Reading package lists... Done
 Building dependency tree... Done
 Reading state information... Done
 Traceback (most recent call last):
   File "/home/bas/git/release-team/release.debian.org/bin/resolve-dependencies.py", 
line 216, in 
 sys.exit(main())
  ^^
   File 
"/home/bas/git/release-team/release.debian.org/bin/resolve-dependencies.py", 
line 212, in main
 return resolve_dependencies()
   File 
"/home/bas/git/release-team/release.debian.org/bin/resolve-dependencies.py", 
line 97, in resolve_dependencies
 cache.update(apt.progress.text, source_list)
 
 apt_pkg.Error: E:Could not open lock file /var/lib/apt/lists/lock - open (13: 
Permission denied), E:Unable to lock directory /var/lib/apt/lists/


   apt_pkg.Error: E:Could not open lock file /var/lib/apt/lists/lock - open 
(13: Permission denied), E:Unable to lock directory /var/lib/apt/lists/


This sounds like you are trying to access something created for the unshared
user as the normal user?


No, this is python-apt running outside the chroot as also hinted by the 
sources.list for trixie.

Running the script directory instead of via unshare fails in the same way 
because my unprivileged user is not allowed to write those directories:

 $ ~/git/release-team/release.debian.org/bin/resolve-dependencies.py -vdp opencv -u 
2>&1 | tee /tmp/resolve-dependencies.log
 Resolving dependencies for: opencv
 Chroot already exists: /var/tmp/testing-chroot
 config:
 RootDir "/var/tmp/testing-chroot";

 list:
 [http://ftp.nl.debian.org/debian/' 
dist='trixie' is_trusted='1'>,
  http://ftp.nl.debian.org/debian/' 
dist='trixie-updates' is_trusted='1'>,
  http://security.debian.org/debian-security/' dist='trixie-security' 
is_trusted='1'>,
  http://ftp.nl.debian.org/debi

Bug#1120799: Using python-apt's apt_pkg with a chroot

2025-12-02 Thread Johannes Schauer Marin Rodrigues
Hi,

Quoting Sebastiaan Couwenberg (2025-12-02 18:36:00)
> Using python-apt's apt_pkg with a chroot turns out to be non-trivial unlike 
> apt.cache.
> 
> I'm running a script [0] on a trixie system and need to interact with the 
> cache in a testing chroot.
> 
> The chroot is created with mmdebstrap --mode=unshare, and the script is run 
> via unshare as well.

maybe this is an XY problem.

Why do you need a full chroot for something that is as far as I get from the
script just a "I want apt to resolve the dependencies with my custom
sources.list"? This sounds like something like chdist is doing?

Maybe the mmdebstrap man page has an example which helps you. It is a snippet
which is the very bare-bones of what mmdebstrap does with a few thousand more
lines of code:


mkdir -p "$2/etc/apt" "$2/var/cache" "$2/var/lib"
cat << END > "$2/apt.conf"
Apt::Architecture "$(dpkg --print-architecture)";
Apt::Architectures "$(dpkg --print-architecture)";
Dir "$(cd "$2" && pwd)";
Dir::Etc::Trusted "$(eval "$(apt-config shell v Dir::Etc::Trusted/f)"; 
printf %s "$v")";
Dir::Etc::TrustedParts "$(eval "$(apt-config shell v 
Dir::Etc::TrustedParts/d)"; printf %s "$v"

END
echo "deb http://deb.debian.org/debian/ $1 main" > "$2/etc/apt/sources.list"
APT_CONFIG="$2/apt.conf" apt-get update
APT_CONFIG="$2/apt.conf" apt-get --yes --download-only install '?essential'
for f in "$2"/var/cache/apt/archives/*.deb; do dpkg-deb --extract "$f" 
"$2"; done
chroot "$2" sh -c "dpkg --install --force-depends 
/var/cache/apt/archives/*.deb"


> Setting RootDir in the config does not result in the chroot paths to be used:

I think you need Dir.

>   apt_pkg.Error: E:Could not open lock file /var/lib/apt/lists/lock - open 
> (13: Permission denied), E:Unable to lock directory /var/lib/apt/lists/

This sounds like you are trying to access something created for the unshared
user as the normal user?

Thanks!

cheers, josch

signature.asc
Description: signature


Bug#1120799: Using python-apt's apt_pkg with a chroot

2025-12-02 Thread Sebastiaan Couwenberg

Using python-apt's apt_pkg with a chroot turns out to be non-trivial unlike 
apt.cache.

I'm running a script [0] on a trixie system and need to interact with the cache 
in a testing chroot.

The chroot is created with mmdebstrap --mode=unshare, and the script is run via 
unshare as well.

Setting RootDir in the config does not result in the chroot paths to be used:

 $ unshare --map-auto --map-user=65536 --map-group=65536 --keep-caps -- 
./bin/resolve-dependencies.py -vdp opencv -u 2>&1 | tee 
/tmp/resolve-dependencies.log
 Resolving dependencies for: opencv
 Chroot already exists: /var/tmp/testing-chroot
 config:
 RootDir "/var/tmp/testing-chroot";

 list:
 [http://ftp.nl.debian.org/debian/' 
dist='trixie' is_trusted='1'>,
  http://ftp.nl.debian.org/debian/' 
dist='trixie-updates' is_trusted='1'>,
  http://security.debian.org/debian-security/' dist='trixie-security' 
is_trusted='1'>,
  http://ftp.nl.debian.org/debian/' 
dist='trixie-backports' is_trusted='1'>,
  http://debug.mirrors.debian.org/debian-debug/' dist='trixie-debug' 
is_trusted='1'>]
 Reading package lists... Done
 Building dependency tree... Done
 Reading state information... Done
 Traceback (most recent call last):
   File "/home/bas/git/release-team/release.debian.org/bin/resolve-dependencies.py", 
line 216, in 
 sys.exit(main())
  ^^
   File 
"/home/bas/git/release-team/release.debian.org/bin/resolve-dependencies.py", 
line 212, in main
 return resolve_dependencies()
   File 
"/home/bas/git/release-team/release.debian.org/bin/resolve-dependencies.py", 
line 97, in resolve_dependencies
 cache.update(apt.progress.text, source_list)
 
 apt_pkg.Error: E:Could not open lock file /var/lib/apt/lists/lock - open (13: 
Permission denied), E:Unable to lock directory /var/lib/apt/lists/

How can apt_pkg be used with a chroot?

apt.Cache(rootdir) works, but it does not provide access to source packages 
like apt_pkg.SourceRecords.

[0] 
https://salsa.debian.org/sebastic/release.debian.org/-/blob/ce71f7e543283c7fcca0a701fe22667ae7a188a2/bin/resolve-dependencies.py

Kind Regards,

Bas

Please CC me as I'm not subscribed to the list.

--
 PGP Key ID: 4096R/6750F10AE88D4AF1
Fingerprint: 8182 DE41 7056 408D 6146  50D1 6750 F10A E88D 4AF1