GithubHelp home page GithubHelp logo

vn971 / rua Goto Github PK

View Code? Open in Web Editor NEW
419.0 10.0 38.0 1.14 MB

Build tool for Arch Linux providing control, review and jailed build options

License: GNU General Public License v3.0

Shell 5.26% Rust 94.74%
archlinux aur arch-user-repository namespaces

rua's Introduction

RUA Rust ShellCheck crates.io

RUA is a build tool for ArchLinux, AUR. Its features:

  • Allows local patch application
  • Provides detailed information:
    • show upstream changes upon package upgrade
    • see code problems in PKGBUILD via shellcheck, taking care of special variables
    • warn if SUID files are present in an already built package, and show them
    • show file list, executable list and INSTALL script in already built packages
  • Minimize user distractions:
    • verify all build scripts once, build without interruptions
    • group built packages for batch review
  • Uses a security namespace jail:
    • supports --offline builds
    • builds in isolated filesystem, see safety section below
    • uses seccomp to limit available syscalls (e.g. the build cannot call ptrace)
    • the build cannot execute sudo (filesystem is mounted with nosuid)
  • Written in Rust

Use

rua search wesnoth

rua info freecad

rua install pinta # install or upgrade a package

rua upgrade # upgrade all AUR packages. You can selectively ignore packages by using --ignore or adding them to IgnorePkg in pacman.conf (same as with non-AUR packages and pacman). You can upgrade only specific packages with rua install A B C.

rua shellcheck path/to/my/PKGBUILD # run shellcheck on a PKGBUILD, discovering potential problems with the build instruction. Takes care of PKGBUILD-specific variables.

rua tarcheck xcalib.pkg.tar # if you already have a *.pkg.tar package built, run RUA checks on it (SUID, executable list, INSTALL script review etc).

rua builddir --offline /path/to/pkgbuild/directory # build a directory.

rua --help; rua subcommand --help # shows CLI help

Install dependencies

sudo pacman -S --needed --asdeps git base-devel bubblewrap-suid libseccomp xz shellcheck cargo

Install (the AUR way)

sudo pacman -S base-devel git
git clone https://aur.archlinux.org/rua.git
cd rua
makepkg -si

In the web interface, package is rua.

Install (the Rust way)

RUSTUP_TOOLCHAIN=stable cargo install --force rua

This will not include bash/zsh/fish completions, but everything else should work.

How it works / directories

directory meaning
~/.config/rua/pkg/ Step 1, directory where AUR packages are cloned into. You review and make local modifications here
~/.cache/rua/build/ Step 2, reviewed packages are copied here, and then built
~/.local/share/rua/checked_tars/ Step 3, directory where built and tarcheck-ed packages are stored (*.pkg.tar.xz)
~/.config/rua/wrap_args.d/ entrypoint for basic configuration of the security wrapper script
~/.config/rua/.system/ internal files
$GNUPGHOME/pubring.kbx
$GNUPGHOME/pubring.gpg
read-only access to these two files is granted when building, to allow signature verification
All other files All other files in ~ are not accessed by RUA and inaccessible by built packages (see Safety section below)

Note that directories above follow the XDG specification, so XDG_CONFIG_HOME environment variable would override ~/.config, XDG_CACHE_HOME would override ~/.cache and XDG_DATA_HOME would override ~/.local/share.

How it works / reviewing

Knowing the underlying machinery is not required to work with RUA, but if you're curious anyway, this section is for you.

All AUR packages are stored in designated git repositories, with upstream/master pointing to remote AUR head and local master meaning your reviewed and accepted state. Local branch does not track the remote one.

RUA works by fetching remote updates when needed, presenting remote changes to you and merging them if you accept them. Merging and basic diff view are built-in commands in RUA, and you can drop to shell and do more from git CLI if you want.

How it works / dependency grouping and installation

RUA will:

  1. Fetch the AUR package and all recursive dependencies.
  2. Prepare a summary of all pacman and AUR packages that will need installing. Show the summary to the user, confirm proceeding.
  3. Iterate over all AUR dependencies and ask to review the repo-s. Once we know that user really accepts all recursive changes, proceed.
  4. Propose installing all pacman dependencies.
  5. Build all AUR packages of maximum dependency "depth".
  6. Let the user review built artifacts (in batch).
  7. Install them. If any more packages are left, go two steps up.

If you have a dependency structure like this:

your_original_package
├── dependency_a
│   ├── a1
│   └── a2
└── dependency_b
    ├── b1
    └── b2

RUA will thus interrupt you 3 times, not 7 as if it would be plainly recursive. It also won't disrupt you if it knows recursion breaks down the line (with unsatisfiable dependencies).

Limitations

  • This tool focuses on AUR packages only, you cannot -Suy your system with it. Please use pacman for that.
  • Optional dependencies (optdepends) are not installed. They are skipped. Please check them out manually when you review PKGBUILD.
  • The tool does not handle versions. It will always install the latest version possible, and it will always assume that latest version is enough.
  • Development packages such as "-git" packages are only rebuilt when running rua upgrade --devel. No version checks are done to avoid unnecessary rebuilds. Merge requests welcomed.
  • Unless you explicitly enable it, builds do not share user home (~). This may result in maven/npm/cargo/whatever dependencies re-downloading with each build. See safety section below on how to whitelist certain directories.
  • Environment variables "PKGDEST" and "BUILDDIR" of makepkg.conf are not supported. Packages are built in isolation from each other, artifacts are stored in standard locations of this tool.
  • Due of safety restrictions, X11 access might not work during build.
  • Also due to safety restrictions, ccache usage will fail during build.
  • Due to a bug in fakeroot, creation of root-owned packages inside PKGBUILD-s package() does not work. This happens when archives are extracted in package() function. Doing it in prepare() or giving a key like tar --no-same-owner is the work-around.

Safety

Do not install AUR packages you don't trust. RUA only adds build-time isolation and install-time control/review.

When building packages, RUA uses the following filesystem isolation:

  • Build directory is mounted read-write.
  • Files "$GNUPGHOME"/pubring.kbx and "$GNUPGHOME"/pubring.gpg are mounted read-only (if exists). This allows signature verification to work.
  • The rest of ~ is not visible to the build process, mounted under tmpfs.
  • /tmp and /dev and /proc are re-mounted with empty tmpfs, devtmpfs and procfs accordingly.
  • The rest of / is mounted read-only.
  • You can whitelist/add your mount points by configuring "wrap_args". See example in ~/.config/rua/.system/wrap_args.sh.example.

Additionally, all builds are run in a namespace jail, with seccomp enabled and user, ipc, pid, uts, cgroup being unshared by default. If asked from CLI, builds can be run in offline mode.

Other

The RUA name is an inversion of "AUR".

This work was made possible by the excellent libraries of raur, srcinfo and many others.

Project is shared under GPLv3+. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project (rua) by you, shall be licensed as GPLv3+, without any additional terms or conditions.

For authors, see Cargo.toml and git history.

rua's People

Contributors

aacunningham avatar bbx0 avatar cedws avatar cleonyc avatar epitstickpan avatar gustafla avatar herrvonvoid avatar intgr avatar joanbm avatar micwoj92 avatar morganamilo avatar mqus avatar nolik avatar raphcode avatar senden9 avatar vn971 avatar vukodrakkeinen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rua's Issues

introduce compile-time options for alpm: "shelling" or "linking"

Currently, rua always uses the linked library alpm.rs (with underlying bindings to alpm/pacman) to determine installed packages, installable packages, packages outside of main repos, etc.

This is not always desireable as it will break with each ".so" change of the underlying native library. Futhermore, it breaks when switching from pacman to pacman-git and back. Yet we only use very basic information from alpm -- something we can easily get by calling pacman as well.

The downside of calling pacman to obtain information is a bit of speed and unnecessary resource consumption.

The proposal is to have two compile-time options to chose one way of doing it or another. In Rust terms, these are crate features.

Anything that requires AUR dependencies to build now fails.

The reasoning behind commit 1925fc2 really confuses me. Skipping dependency checks is a bad idea. If the issue is that makepkg is complaining about missing deps... then your problem is you need to have the deps installed, not just skip dependency checks.

As a result, anything that requires an AUR package to build now fails under rua.

Missing syscall when installing streamlink

I tried to install streamlink-git AUR, and I get the following error:

...
UPDATING build/lib/streamlink/_version.py
set build/lib/streamlink/_version.py to '1.2.0+41.gcc32730'
running build_sphinx
Running Sphinx v2.2.1
making output directory... done
/usr/lib/python3.8/site-packages/sphinx/util/compat.py:30: RemovedInSphinx30Warning: The config variable "source_parsers" is deprecated. Please update your extension for the parser and remove the setting.
  warnings.warn('The config variable "source_parsers" is deprecated. '
/usr/lib/python3.8/site-packages/sphinx/util/compat.py:36: RemovedInSphinx30Warning: app.add_source_parser() does not support suffix argument. Use app.add_source_suffix() instead.
  app.add_source_parser(suffix, parser)
building [mo]: targets for 0 po files that are out of date
building [man]: all manpages
updating environment: [new config] 13 added, 0 changed, 0 removed
/usr/lib/python3.8/site-packages/recommonmark/parser.py:75: UserWarning: Container node skipped: type=document
  warn("Container node skipped: type={0}".format(mdnode.t))
/home/kuon/.cache/rua/build/streamlink-git/PKGBUILD: line 41:   720 Bad system call         (core dumped) python setup.py build_sphinx -b man
==> ERROR: A failure occurred in build().

It installs fine with makepkg.

Coredump:

           PID: 695330 (python)
           UID: 1000 (kuon)
           GID: 1000 (kuon)
        Signal: 31 (SYS)
     Timestamp: Fri 2019-11-15 21:02:46 CET (3min 41s ago)
  Command Line: python setup.py build_sphinx -b man
    Executable: /usr/bin/python3.8
 Control Group: /user.slice/user-1000.slice/session-1.scope
          Unit: session-1.scope
         Slice: user-1000.slice
       Session: 1
     Owner UID: 1000 (kuon)
       Boot ID: 3a90871f2e1042bf847e13c2b23b0c32
    Machine ID: b20570e1eb354484842cd3f69b841431
      Hostname: yoda
       Storage: /var/lib/systemd/coredump/core.python.1000.3a90871f2e1042bf847e13c2b23b0c32.695330.1573848166000000000000.lz4
       Message: Process 695330 (python) of user 1000 dumped core.
                
                Stack trace of thread 720:
                #0  0x00007f09fe442e9d syscall (libc.so.6)
                #1  0x00007f09f8fe9988 n/a (libblas.so.3)
                #2  0x00007f09f8fe9dca blas_memory_alloc (libblas.so.3)
                #3  0x00007f09f8fea932 blas_thread_init (libblas.so.3)
                #4  0x00007f09f8dd7084 gotoblas_init (libblas.so.3)
                #5  0x00007f09fe59872a call_init.part.0 (ld-linux-x86-64.so.2)
                #6  0x00007f09fe598831 _dl_init (ld-linux-x86-64.so.2)
                #7  0x00007f09fe59c603 dl_open_worker (ld-linux-x86-64.so.2)
                #8  0x00007f09fe482d79 _dl_catch_exception (libc.so.6)
                #9  0x00007f09fe59beee _dl_open (ld-linux-x86-64.so.2)
                #10 0x00007f09fdfad34c n/a (libdl.so.2)
                #11 0x00007f09fe482d79 _dl_catch_exception (libc.so.6)
                #12 0x00007f09fe482e13 _dl_catch_error (libc.so.6)
                #13 0x00007f09fdfadab9 n/a (libdl.so.2)
                #14 0x00007f09fdfad3da dlopen (libdl.so.2)
                #15 0x00007f09fe1f5ba5 _PyImport_FindSharedFuncptr (libpython3.8.so.1.0)
                #16 0x00007f09fe1f5e3f _PyImport_LoadDynamicModuleWithSpec (libpython3.8.so.1.0)
                #17 0x00007f09fe1f606a n/a (libpython3.8.so.1.0)
                #18 0x00007f09fe104957 n/a (libpython3.8.so.1.0)
                #19 0x00007f09fe113f11 PyVectorcall_Call (libpython3.8.so.1.0)
                #20 0x00007f09fe168841 _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #21 0x00007f09fe1331ea _PyEval_EvalCodeWithName (libpython3.8.so.1.0)
                #22 0x00007f09fe133f9f _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #23 0x00007f09fe167aad _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #24 0x00007f09fe133f0b _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #25 0x00007f09fe163a11 _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #26 0x00007f09fe133f0b _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #27 0x00007f09fe16361c _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #28 0x00007f09fe133f0b _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #29 0x00007f09fe16361c _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #30 0x00007f09fe133f0b _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #31 0x00007f09fe16361c _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #32 0x00007f09fe133f0b _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #33 0x00007f09fe101ec8 n/a (libpython3.8.so.1.0)
                #34 0x00007f09fe128b93 _PyObject_CallMethodIdObjArgs (libpython3.8.so.1.0)
                #35 0x00007f09fe0f7a2a PyImport_ImportModuleLevelObject (libpython3.8.so.1.0)
                #36 0x00007f09fe167041 _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #37 0x00007f09fe1331ea _PyEval_EvalCodeWithName (libpython3.8.so.1.0)
                #38 0x00007f09fe133e0a PyEval_EvalCodeEx (libpython3.8.so.1.0)
                #39 0x00007f09fe1bfa9c PyEval_EvalCode (libpython3.8.so.1.0)
                #40 0x00007f09fe1fba23 n/a (libpython3.8.so.1.0)
                #41 0x00007f09fe104957 n/a (libpython3.8.so.1.0)
                #42 0x00007f09fe113f11 PyVectorcall_Call (libpython3.8.so.1.0)
                #43 0x00007f09fe168841 _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #44 0x00007f09fe1331ea _PyEval_EvalCodeWithName (libpython3.8.so.1.0)
                #45 0x00007f09fe133f9f _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #46 0x00007f09fe167aad _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #47 0x00007f09fe133f0b _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #48 0x00007f09fe163a11 _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #49 0x00007f09fe133f0b _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #50 0x00007f09fe16361c _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #51 0x00007f09fe133f0b _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #52 0x00007f09fe16361c _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #53 0x00007f09fe133f0b _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #54 0x00007f09fe101ec8 n/a (libpython3.8.so.1.0)
                #55 0x00007f09fe128b93 _PyObject_CallMethodIdObjArgs (libpython3.8.so.1.0)
                #56 0x00007f09fe0f7a2a PyImport_ImportModuleLevelObject (libpython3.8.so.1.0)
                #57 0x00007f09fe16325a n/a (libpython3.8.so.1.0)
                #58 0x00007f09fe155977 PyCFunction_Call (libpython3.8.so.1.0)
                #59 0x00007f09fe168841 _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #60 0x00007f09fe1331ea _PyEval_EvalCodeWithName (libpython3.8.so.1.0)
                #61 0x00007f09fe133f9f _PyFunction_Vectorcall (libpython3.8.so.1.0)
                #62 0x00007f09fe16361c _PyEval_EvalFrameDefault (libpython3.8.so.1.0)
                #63 0x00007f09fe133794 _PyEval_EvalCodeWithName (libpython3.8.so.1.0)

multilib dependencies cause an error

Package I tried: https://aur.archlinux.org/packages/foobar2000/

It has Wine (arch repos, i think) as a dependency.

[eliaso@home ~]$ rua install foobar2000
foobar2000 depends on AUR package wine. Trying to fetch it...
thread 'main' panicked at 'Repository wine does not have an SRCINFO file. Does this package exist in AUR?', src/aur.rs:38:2
stack backtrace:
   0: <unknown>
   1: <unknown>
   2: <unknown>
   3: <unknown>
   4: <unknown>
   5: <unknown>
   6: <unknown>
   7: <unknown>
   8: <unknown>
   9: <unknown>
  10: <unknown>
  11: <unknown>
  12: __libc_start_main
  13: <unknown>

Frustrated: confusing behavior when installing xen

I enabled multilib from pacman first and ran rua install xen
After a very looooooooong wait the compilation is finished.
rua asked me

Package /home/b1f6c1c4/.cache/rua/xen/build/target/xen-4.11.0-2-x86_64.pkg.tar.xz has no SUID files.
[I]=show install file, [E]=list executable files, [L]=list all files, [T]=run shell to inspect, [O]=ok, proceed.

And I typed i to view the install file. It looks nice. Afterwards,

Package /home/b1f6c1c4/.cache/rua/xen/build/target/xen-4.11.0-2-x86_64.pkg.tar.xz has no SUID files.
[I]=show install file, [E]=list executable files, [L]=list all files, [T]=run shell to inspect, [O]=ok, proceed. o


Package /home/b1f6c1c4/.cache/rua/xen/build/target/xen-docs-4.11.0-2-any.pkg.tar.xz has no SUID files.
[E]=list executable files, [L]=list all files, [T]=run shell to inspect, [O]=ok, proceed. o

Packages need to be installed:

    pacman -U --needed /home/b1f6c1c4/.cache/rua/xen/checked_tars/xen-docs-4.11.0-2-any.pkg.tar.xz

Enter S to `sudo` install it, or install manually and press M when done. s
loading packages...
resolving dependencies...
looking for conflicting packages...

Packages (1) xen-docs-4.11.0-2

Total Installed Size:  3.94 MiB

:: Proceed with installation? [Y/n]
(1/1) checking keys in keyring                     [######################] 100%
(1/1) checking package integrity                   [######################] 100%
(1/1) loading package files                        [######################] 100%
(1/1) checking for file conflicts                  [######################] 100%
(1/1) checking available disk space                [######################] 100%
:: Processing package changes...
(1/1) installing xen-docs                          [######################] 100%
:: Running post-transaction hooks...
(1/1) Arming ConditionNeedsUpdate...
Packages need to be installed:

    pacman -U --needed /home/b1f6c1c4/.cache/rua/xen/checked_tars/xen-docs-4.11.0-2-any.pkg.tar.xz

Enter S to `sudo` install it, or install manually and press M when done. s
loading packages...
warning: xen-docs-4.11.0-2 is up to date -- skipping
 there is nothing to do
Packages need to be installed:

    pacman -U --needed /home/b1f6c1c4/.cache/rua/xen/checked_tars/xen-docs-4.11.0-2-any.pkg.tar.xz

Enter S to `sudo` install it, or install manually and press M when done. s
loading packages...
warning: xen-docs-4.11.0-2 is up to date -- skipping
 there is nothing to do
Packages need to be installed:

    pacman -U --needed /home/b1f6c1c4/.cache/rua/xen/checked_tars/xen-docs-4.11.0-2-any.pkg.tar.xz

Enter S to `sudo` install it, or install manually and press M when done. s
loading packages...
warning: xen-docs-4.11.0-2 is up to date -- skipping
 there is nothing to do
Packages need to be installed:

    pacman -U --needed /home/b1f6c1c4/.cache/rua/xen/checked_tars/xen-docs-4.11.0-2-any.pkg.tar.xz

Enter S to `sudo` install it, or install manually and press M when done. m

Immediately I tried to ls /boot and ls /etc/xen to configure xen, but I didn't see the files installed. So I, without thinking about it, typed rua install xen and hit enter.
It was not until I saw makepkg started downloading xen-4.11.0.tar.gz that I realized rua deleted /home/b1f6c1c4/.cache/rua/xen, INCLUDING targets, WITHOUT noticing me at all.

So two problems:

  1. Why rua fails silently when installing xen-4.11.0-2-x86_64.pkg.tar.xz?
  2. Why rua delete cache dir without any notification ? Especially when trying to purge a huge package that failed during installation ?

respect pacman HoldPkg packages when doing upgrade

Currently, RUA tries to offer upgrades for any AUR packages that have upstream updates. We also have pacman-s HoldPkg, which serves a different, but similar purpose (its main purpose is to instruct pacman on its actions). Re-using it in RUA seems like a straightforward action.

Opinions welcomed.

Possible implementation 1: this list of ignored packages can be obtained by pacconf --null HoldPkg. It will require pacconf in (optional?) dependencies though.

Possible implementation 2: this list can be obtained by using pacman-conf HoldPkg. This utility is part of pacman package, and thus is always present on the target system. It does not support the "null terminated" splitting, but we don't need that because pacman.conf is newline-split anyway.

feature request: offer to run shellcheck on PKGBUILD

Offering to run shellcheck on PKGBUILD-s can help reviewing. The problem is that a pure invocation of shellcheck PKGBUILD will give numerous warnings:

  • declared in PKGBUILD but "unused" variables like $pkgname
  • use of undeclared variables $srcdir, $pkgdir
  • maybe something else

These would better be handled somehow smartly. One approach that I can think of is to create a wrapper "script" which declares variables like $srcdir, then sources PKGBUILD and then uses the declared variables like $pkgname somehow. Maybe there are other solutions as well.

implement upstream AUR diff

When installing new versions of an already installed package, the user should be able to review changes made upstream. This includes PKGBUILD and other files.

Use better name instead of "jailbuild"

It's sometimes assumed by people that "jailbuild" will build a remote package instead of local directory. A command name like builddir might be better. If this gets done, feel free to rename some Rust methods as well, so that "jailbuild" terminology is completely gone.

add support for namcap

Currently, RUA has a step where built packages are analyzed. It seems very logical to add namcap to the list of possible actions. When doing this feature, don't forget to add namcap to optdepends. Also, README.md must be updated suggesting to install namcap.

visualize dependencies as a tree

When installing or upgrading packages, visualize the the expected changes / depedency hierarchy with a tree:

gam  (AUR)
├── python-dateutil
├── python-google-api-python-client
├── python-google-auth-httplib2
├── python-google-auth-oauthlib  (AUR)
│   └── python-requests-oauthlib
├── python-google-auth
├── python-httplib2
├── python-mock
├── python-passlib
└── python-pytest

As a first implementation, just printing AUR deps could work. This can be further improved by printing pacman deps, showing broken AUR/pacman deps right in the tree, and maybe visually separate AUR and "repo" packages with color.

implement zstd archive format

ArchLinux recently announced that they will use/support zstd archive format: https://www.archlinux.org/news/required-update-to-recent-libarchive/

Support for it in RUA is not urgent/critical (it will just build in archives it knows), but is ultimately desired to move along with upstream development. Especially the tarcheck command, which should be able to look into packages built with e.g. just makepkg.

Rust has some support via:

feature request: option for upgade to only output

It would be nice, if there was an option for rua upgrade that would not prompt to update the packages, but instead only list them.

This would be useful, if you only want to check if there are outdated packages (for instance in a script to regularily check the amount of outdated packages and print them somewhere (e.g. polybar))

Panic on package build failure.

I am trying to install some packages and am getting a panic on src/wrapped.rs:61:2. The backtrace is pretty unhelpful, but it looks like the command that was being executed didn't return 0.

Ideally this shouldn't panic, but should just print a warning or error.

Integrate with an AUR JSON API library

As posted by @Morganamilo in #22 (comment):

For the RPC there's https://github.com/rusty-crates/aur.rs and https://gitlab.com/davidbittner/raur. I assume you know about the former since you opened an issue there.

The latter once seems much simpler to use and the code is more simple.

But then the former extents reqwest/hyper via traits which I guess may be the more rust like approach? This former is probably better too if you want to split up requests asynchronously (which you probably do due to the 4kb url limit).

Although assuming all my PRs eventually get merged they should both have an almost identical api anyway.

Solving this would also make GH-13 very easy.

rua installation of git packages broken

Currently, rua uses a whitelist of package names when checking tar files (to install packages from split pkgbases separately). This is problematic for -git packages, and generally, packages where .SRCINFO version differs from PKGBUILD version.

This was introduced recently and needs to be fixed.

Repeated dependencies installed in incorrect order

I ran into this while installing ruby-gollum. When a package (in this case ruby-nokogiri) is depended upon multiple times and a later depending package is deeper than the first, it will be installed after some of the packages that depend on it and the makepkg will fail. This is because packages are installed in order of the depth of the first time the package is required, and instead they need to be in order of the depth of the deepest depending package.

rua upgrade command does not filter out lower versions

If you have an AUR package where the version can dynamically change, locally installed package will have higher version than that written in .SRCINFO of the package. rua upgrade action should detect downgrade and exclude such packages.

It doesn't hurt to upgrade a dynamically changing package though (it's probably a -git-like one).

Usability: group PKGBUILD verification with reviewing of built artifacts

This is a proposal to change package review process.
For example, let's consider package A, that depends on N and M, which in turn depend on X, Y, Z.

The current schema looks like this:

  • let user review repo-s for A, N, M, X, Y, Z
  • build X Y Z, review artifacts for Z Y Z, install
  • build N, M, review artifacts for N M, install
  • build A, review artifact, install

This is formally correct, but there is a problem. You might already forget what was in PKGBUILD of A by the time you're reviewing artifact for A. You might want the steps to be closer in time instead. Same as in programming languages: if you can move variable declaration closer to usage, do it. It saves you from mistakes and eases mental load.

This seems like a nice feature for RUA to have, considering that we already try to ease up reviewing process and reduce interruptions.

Implement search

Display the user hits for the search subcommand. For the printing we can use something like prettytable plus the AUR search api.

At the moment the user gets only a link that needs to be opend in some browser, go back to the terminal & type the install command. This is not the most ergonomic workflow.

No such file or directory

A error

thread 'main' panicked at 'Failed to find config dir for locking: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/libcore/result.rs:999:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

return when i run rua search some-pkg-name.

So i mkdir -p ~/.config/rua, the error is not display

panic when removing non-empty stale build directory

to reproduce, do something like:

  • Control-c a build midway through
  • Attempt to re-run install, rua will tell you that it will remove the build dir.
  • Be okay with that
  • panic!

Such as:

❯ rua install infer
WARNING: your AUR repo is up-to-date.
If you continue, the build directory will be removed and the build will be re-run.
If you don't want that, consider resolving the situation manually,
for example:    rua builddir "/home/jimmy/.cache/rua/build/infer"

Reviewing "/home/jimmy/.config/rua/pkg/infer".
[S]=run shellcheck on PKGBUILD, [D]=(identical to upstream, empty diff), [T]=run shell to edit/inspect, [O]=ok, use package o
thread 'main' panicked at 'Failed to remove old build dir "/home/jimmy/.cache/rua/build/infer", No such file or directory (os error 2)', src/action_install.rs:119:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
                                                                  [ 7s168 | Oct 17 10:53AM ]
❯ rua builddir /home/jimmy/.cache/rua/build/infer
==> ERROR: PKGBUILD does not exist.
Build failed with exit code 4 in /home/jimmy/.cache/rua/build/infer
                                                                  [ 0s088 | Oct 17 10:53AM ]
❯ exa /home/jimmy/.cache/rua/build/
bcc             cargo-flamegraph  cargo-watch     infer              slack-desktop
bpftrace        cargo-fuzz        git-series      leiningen
cargo-crev-git  cargo-pkgbuild    git-series-git  onefetch
cargo-edit      cargo-tree        hexyl-bin       shellcheck-static
                                                                  [ 0s001 | Oct 17 10:53AM ]
❯ exa /home/jimmy/.cache/rua/build/infer
infer  pkg  src

Static pkgbuild is easy to bypass

Giving the srcinfo

pkgname = foo
pkgver = 1
pkgrel = 1
arch = any
pkgdesc = this';echo hacked;#

produces the pkgbuild

pkgname+=('foo')
pkgver='1'
pkgrel='1'
arch+=('any')
pkgdesc='this''';echo hacked;#'

Which when run through bash or makepkg outputs hacked.

Personally I think trying to secure pkgbuilds like this is a bad idea in the first place. Instead I think it's best to just have the user vet the pkgbuild before downloading sources.

implement Update functionality

Hi, all. As a comma Arch user i wanna have update functionality of all available for update packages.
(something like yay main command).
I able to try implement it, and it will be grate to hear you advice about way to implement it.

What is the point of clean_package_name?

I understand makepkg has these restrictions on pkgname.

I could some what understand if this function returned an error, but instead is actually edits the depend's name.

What does this aim to solve? If the package had an invalid depend then you assume the depend will fail to match a package anyway and you end up with a clear missing package error. If the depend does match something then fine, so what?

makepkg has it's own lint system that makes invalid stuff fail to build, therefore invalid stuff should not be on the AUR. I think we should just rely on makepkg's linting instead of checking stuff for ourselves.

bwrap: Can't mkdir ~/.gnupg/openpgp-revocs.d: Read-only file system thread 'main' panicked at 'Failed to build package', src/wrapped.rs:61:2

➜  ~ rua install sound-theme-smooth
Verifying package sound-theme-smooth. [V]=view PKGBUILD, [E]=edit PKGBUILD, [I]=run shell to inspect, [O]=ok, use package: o
bwrap: Can't mkdir /home/eliaso/.gnupg/openpgp-revocs.d: Read-only file system
thread 'main' panicked at 'Failed to build package', src/wrapped.rs:61:2
stack backtrace:
   0: <unknown>
   1: <unknown>
   2: <unknown>
   3: <unknown>
   4: <unknown>
   5: <unknown>
   6: <unknown>
   7: <unknown>
   8: <unknown>
   9: __libc_start_main
  10: <unknown>

Improper quoting of PKGBUILD.static

static_pkgbuild doesn't properly quote strings. This makes packages with apostrophes in their descriptions, such as ruby-stringex, fail to build.

/home/aur/.cache/rua/ruby-stringex/build/PKGBUILD.static: line 13: unexpected EOF while looking for matching `''
/home/aur/.cache/rua/ruby-stringex/build/PKGBUILD.static: line 14: syntax error: unexpected end of file
==> ERROR: Failed to source /home/aur/.cache/rua/ruby-stringex/build/PKGBUILD.static

(followed by a panic)

Rua always wants to install stuff as deps

When installing an AUR package, the command given always includes --asdeps. This happens for already install explicit packages, and when installing new packages.

v0.6.3-4

morganamilo@Vinyl ~ % rua install downgrader
Downloaded downgrader. V=view PKGBUILD, E=edit PKGBUILD, I=run shell to inspect, O=ok, use the file: o
>>>>>>makepkg --noprepare --nobuild
==> Making package: downgrader 2.0.0-3 (Tue 30 Oct 2018 15:46:09 GMT)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
  -> Cloning Archlinux-downgrader git repo...
Cloning into bare repository '/home/morganamilo/.cache/rua/downgrader/build/Archlinux-downgrader'...
remote: Enumerating objects: 658, done.
remote: Total 658 (delta 0), reused 0 (delta 0), pack-reused 658
Receiving objects: 100% (658/658), 1.42 MiB | 797.00 KiB/s, done.
Resolving deltas: 100% (403/403), done.
==> Validating source files with md5sums...
    Archlinux-downgrader ... Skipped
==> Extracting sources...
  -> Creating working copy of Archlinux-downgrader git repo...
Cloning into 'Archlinux-downgrader'...
done.
==> Sources are ready.
>>>>>>makepkg
==> Making package: downgrader 2.0.0-3 (Tue 30 Oct 2018 15:46:13 GMT)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
  -> Updating Archlinux-downgrader git repo...
Fetching origin
==> Validating source files with md5sums...
    Archlinux-downgrader ... Skipped
==> Extracting sources...
  -> Creating working copy of Archlinux-downgrader git repo...
Switched to a new branch 'makepkg'
==> Starting build()...
gcc -g -c main.c -o main.o -std=c99 -Wno-implicit-function-declaration
g++ main.o cJSON.c -lalpm -lcurl -o downgrader
==> Entering fakeroot environment...
==> Starting package()...
==> Tidying install...
  -> Removing libtool files...
  -> Purging unwanted files...
  -> Removing static library files...
  -> Stripping unneeded symbols from binaries and libraries...
  -> Compressing man and info pages...
==> Checking for packaging issues...
==> Creating package "downgrader"...
  -> Generating .PKGINFO file...
  -> Generating .BUILDINFO file...
/usr/bin/pacman: line 2: /dev/tty: No such device or address
/usr/bin/pacman: line 2: /dev/tty: No such device or address
  -> Generating .MTREE file...
  -> Compressing package...
==> Leaving fakeroot environment.
==> Finished making: downgrader 2.0.0-3 (Tue 30 Oct 2018 15:46:15 GMT)

Package /home/morganamilo/.cache/rua/downgrader/build/target/downgrader-2.0.0-3-x86_64.pkg.tar has no SUID files.
[E]=list executable files, [L]=list all files, [T]=run shell to inspect, [O]=ok, proceed. o

Packages (or dependencies) need to be installed:

    pacman -U --needed --asdeps /home/morganamilo/.cache/rua/downgrader/checked_tars/downgrader-2.0.0-3-x86_64.pkg.tar

Enter S to `sudo` install it, or install manually and press M when done. s
[sudo] 
>>> pacman -U --needed --asdeps /home/morganamilo/.cache/rua/downgrader/checked_tars/downgrader-2.0.0-3-x86_64.pkg.tar
loading packages...
warning: downgrader-2.0.0-3 is up to date -- skipping
 there is nothing to do
>>> pacman -Qi downgrader

Also may as well mention. It looks like you're using pacman -Qi to check for installed packages. You may want to look into pacman -T.

depends_arch should not assume pacman architecture == uname

For architecture specific fields (e.g. depends_x86_64) the architecture should correspond to the architecture defined in pacman.conf, not the system architecture.

On x84_64 this doesn't really matter as pacman.conf and uname happen to agree.

But on other architectures like arm, uname -m gives armv7l while pacman.conf contains Architecture = armv7h.

asdeps and explicit are not handled properly

Currently rua uses a pretty naive solution to figure out is a package should be installed explicitly.

There's currently two problems with it:

  1. It assumes an entire pkgbase is either asdeps or explicit. This it not the case, for example if I install libc++ then libc++abi will get pulled in as a dependency. Currently rua will suggest them both be explicit.

  2. Install reason should not change when upgrading a package. Say I already have foo=1 installed explicitly, then I want to install bar and bar depends on foo=2. Then rua would pull that in as a dependency and suggest I install it with --asdeps, changing the install reason.

Do note due to rua not handling versioned deps I think point 2 is unreachable because rua would consider the dep foo=2 satisfied even though it should not be.

Support insecure builds for docker?

Currently, RUA does not support building packages without the namespace jail (bubblewrap). Unfortunately, it does not work in e.g. docker.

Adding support for insecure (jail-less) builds could help users of docker, see e.g. #6 (comment)

Rua fails to install split packages where pkgname != pkgbase

For example when installing libc++ rua tries to fetch the libc++abi pkgbuild even though it doesn't exist.

morganamilo@Octavia srcinfo-crate ~git/rua % cargo run install libc++   
    Finished dev [unoptimized + debuginfo] target(s) in 0.09s
     Running `target/debug/rua install libc++`
libc++ depends on AUR package libc++abi=7.0.1-2. Trying to fetch it...
thread 'main' panicked at 'Command failed with exit code Some(128)
Stderr: Cloning into 'aur.tmp'...
fatal: repository 'https://aur.archlinux.org/libc++abi=7.0.1-2.git/' not found

Stdout: ', src/aur_download.rs:15:2
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
   1: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:70
   2: std::panicking::default_hook::{{closure}}
             at src/libstd/sys_common/backtrace.rs:58
             at src/libstd/panicking.rs:200
   3: std::panicking::default_hook
             at src/libstd/panicking.rs:215
   4: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:478
   5: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:385
   6: std::panicking::begin_panic_fmt
             at src/libstd/panicking.rs:340
   7: rua::aur_download::assert_command_success
             at src/aur_download.rs:15
   8: rua::aur_download::fresh_download
             at src/aur_download.rs:54
   9: rua::wrapped::prefetch_aur
             at src/wrapped.rs:140
  10: rua::wrapped::prefetch_aur
             at src/wrapped.rs:162
  11: rua::wrapped::install
             at src/wrapped.rs:260
  12: rua::main
             at src/main.rs:145
  13: std::rt::lang_start::{{closure}}
             at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/rt.rs:64
  14: std::panicking::try::do_call
             at src/libstd/rt.rs:49
             at src/libstd/panicking.rs:297
  15: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:92
  16: std::rt::lang_start_internal
             at src/libstd/panicking.rs:276
             at src/libstd/panic.rs:388
             at src/libstd/rt.rs:48
  17: std::rt::lang_start
             at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/rt.rs:64
  18: main
  19: __libc_start_main
  20: _start

If I try to install libc++abi directly it tries to pull llvm in as a dependency even though it is not a dependency. Hitting M to effectively skip installing it then causes makepkg because of the missing dependency. Even though using makepkg directly works fine.

morganamilo@Octavia srcinfo-crate ~git/rua % cargo run install libc++abi
    Finished dev [unoptimized + debuginfo] target(s) in 0.09s
     Running `target/debug/rua install libc++abi`

In order to install libc++abi, the following pacman packages will need to be installed:
  llvm
And the following AUR packages will need to be built and installed:
  libc++abi

Proceed? [O]=ok, Ctrl-C=abort. o
Verifying package libc++abi. [V]=view PKGBUILD, [E]=edit PKGBUILD, [I]=run shell to inspect, [O]=ok, use package: o
Packages need to be installed:

    pacman -S --asdeps --needed llvm

Enter S to `sudo` install it, or install manually and press M when done. m
==> Making package: libc++abi 3.9.1-1 (Sun 10 Mar 2019 18:32:12 GMT)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Missing dependencies:
  -> llvm
==> ERROR: Could not resolve all dependencies.
thread 'main' panicked at 'Failed to build package', src/wrapped.rs:64:2
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
   1: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:70
   2: std::panicking::default_hook::{{closure}}
             at src/libstd/sys_common/backtrace.rs:58
             at src/libstd/panicking.rs:200
   3: std::panicking::default_hook
             at src/libstd/panicking.rs:215
   4: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:478
   5: std::panicking::begin_panic
             at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/panicking.rs:412
   6: rua::wrapped::build_local
             at src/wrapped.rs:64
   7: rua::wrapped::build_directory
             at src/wrapped.rs:86
   8: rua::wrapped::install_all
             at src/wrapped.rs:213
   9: rua::wrapped::install
             at src/wrapped.rs:267
  10: rua::main
             at src/main.rs:145
  11: std::rt::lang_start::{{closure}}
             at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/rt.rs:64
  12: std::panicking::try::do_call
             at src/libstd/rt.rs:49
             at src/libstd/panicking.rs:297
  13: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:92
  14: std::rt::lang_start_internal
             at src/libstd/panicking.rs:276
             at src/libstd/panic.rs:388
             at src/libstd/rt.rs:48
  15: std::rt::lang_start
             at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/rt.rs:64
  16: main
  17: __libc_start_main
  18: _start

And as another example of this there's clion-jre.

morganamilo@Octavia srcinfo-crate ~git/rua % cargo run install clion-jre 
    Finished dev [unoptimized + debuginfo] target(s) in 0.08s
     Running `target/debug/rua install clion-jre`
thread 'main' panicked at 'Repository clion-jre does not have an SRCINFO file. Does this package exist in AUR?', src/aur_download.rs:55:2
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
   1: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:70
   2: std::panicking::default_hook::{{closure}}
             at src/libstd/sys_common/backtrace.rs:58
             at src/libstd/panicking.rs:200
   3: std::panicking::default_hook
             at src/libstd/panicking.rs:215
   4: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:478
   5: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:385
   6: std::panicking::begin_panic_fmt
             at src/libstd/panicking.rs:340
   7: rua::aur_download::fresh_download
             at src/aur_download.rs:55
   8: rua::wrapped::prefetch_aur
             at src/wrapped.rs:140
   9: rua::wrapped::install
             at src/wrapped.rs:260
  10: rua::main
             at src/main.rs:145
  11: std::rt::lang_start::{{closure}}
             at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/rt.rs:64
  12: std::panicking::try::do_call
             at src/libstd/rt.rs:49
             at src/libstd/panicking.rs:297
  13: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:92
  14: std::rt::lang_start_internal
             at src/libstd/panicking.rs:276
             at src/libstd/panic.rs:388
             at src/libstd/rt.rs:48
  15: std::rt::lang_start
             at /rustc/2aa4c46cfdd726e97360c2734835aa3515e8c858/src/libstd/rt.rs:64
  16: main
  17: __libc_start_main
  18: _start

flatten dependency grouping

Currently, RUA schedules all dependencies of a package to be build strongly before the main package is built. It thus acts as if all dependencies would be "makedepends". If, however, there are few "makedepends" and many "depends", the build queue can be flattened more aggressively. It will thus further reduce the number of distractions that RUA makes for the user, which is an official value for the project.

Tar cannot change ownership to uid 0, gid 0

I am not sure if this is rua's fault (because of the permission architecture it uses), or if the PKGBUILD of the package must be changed.

The package I am trying to install is:

https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=ms-teams

And I get the following errors (truncated, as there is the same error for all files in the archive):

tar: ./usr/share/teams-insiders/version: Cannot change ownership to uid 0, gid 0: Invalid argument
tar: ./usr/share/teams-insiders: Cannot change ownership to uid 0, gid 0: Invalid argument
tar: ./usr/share: Cannot change ownership to uid 0, gid 0: Invalid argument
tar: ./usr: Cannot change ownership to uid 0, gid 0: Invalid argument
tar: .: Cannot change ownership to uid 0, gid 0: Invalid argument
tar: Exiting with failure status due to previous errors
==> ERROR: A failure occurred in package().
    Aborting...
Build failed with exit code 4 in /home/kuon/.cache/rua/build/ms-teams

Adding --no-same-owner to the tax extract command fix it, but I don't know if rua ought to support the PKGBUILD as it is.

implement building ABS (non-AUR) packages

rua’s support for maintaining local patches looks great. The approach of keeping a local git branch and merging from AUR with git is unique as far as I know.

I’ve been using customizepkg together with yaourt for similar functionality. Importantly, this also works with packages from non-AUR official repositories (core, extra, etc.) When a new version becomes available, yaourt can automatically fetch PKGBUILD and associated files from ABS, apply local patches, rebuild, and install. Then when pacman is called, that packaged is skipped since it’s already up to date.

Would it make sense for rua to grow support for ABS packages, for the purpose of maintaining and applying local patches? I realize this is a significant increase in the scope of the project.

(Alternatively, do you know of another AUR helper that does this?)


In addition to other reasons not to use yaourt, it seems a recent server config change broke this feature: fetching for example https://git.archlinux.org/svntogit/packages.git/snapshot/packages/gnome-terminal.tar.gz returns an HTTP 400 error.

Provide information on manual recovery for aborted installation

Subj. In case of broken installation, RUA just exits with the error reason, but doesn't show any steps that could be taken for manual recovery.

Personally, however, I use manual recovery quite often, and I guess other people might want that as well. If this gets implemented, RUA would point to build process leftovers, e.g. ~/.cache/rua/my_package/build/, and mention the possibility to build manually via rua jailbuild ~/.cache/rua/my_package/build/.

When using fish shell, terminal is stuck after inspecting

When I do (with fish shell as login shell):

rua install <pkg>

and at this prompt press T

[S]=run shellcheck on PKGBUILD, [D]=(identical to upstream, empty diff), [T]=run shell to edit/inspect, [O]=ok, use package

I am redirected to a shell inside the package, where I can modify the PKGBUILD, but after exiting that shell with exit or ctrl+d I have that prompt again:

Reviewing "/home/kuon/.config/rua/pkg/cordless-git". 
[S]=run shellcheck on PKGBUILD, [D]=(identical to upstream, empty diff), [T]=run shell to edit/inspect, [O]=ok, use package 

but keys are ignored, I must press Ctrl+C to exit rua.

If I create another user with bash as login shell it works, if I switch this user (using chsh) to fish (to ensurer a blank fish configuration), it doesn't work.

Tested with fish shell 3.0.2.

implement smarter source downloading in `--offline` mode

As raised here by @Morganamilo, #19 (comment) it is sometimes desireable to build a package offline, but assume that PKGBUILD is being read carefully by the user and downloading of sources in it is safe.

One solution would be to have a key like --offline that does exacly that. Unfortunately, however, it'll be 2 separate keys in RUA then, which starts to feel a bit messy.

Any ideas to tackle the problem are welcome.

group information fetching

Сurrently, dependencies of AUR packages are resolved one-by-one, with each unseen AUR package being resolved via a separate HTTP request to https://aur.archlinux.org/rpc

Making grouped requests for a number of AUR packages at once would allow faster information retrieval.

improve detection of package names to install

Currently, rua uses a global whitelist of packages that are needed to install. It is not a per-pkgbase thing.

Making it local to each pkgbase would make the algorithm more simple/straightforward, allowing less mistakes to happen.

The downside is that another makepkg invocation would need to be made (but it's still deemed to be a good thing).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.