New project 'guile-stash'

Announcing Guile-Stash: A New Guile Scheme Utility for Symlink Management with Conflict Resolution

I’m excited to announce the release of Guile-Stash, a utility I’ve developed using Guile Scheme, designed to simplify the management of symbolic links (symlinks) with an added focus on conflict resolution. Guile-Stash allows users to create symlinks for files and directories, offering options to handle existing path conflicts interactively.

What is Guile-Stash?

Guile-Stash is a command-line tool that provides a straightforward way to create symlinks, especially when the potential for conflicts exists. It takes two primary arguments: --target, the directory where you wish to create the symlink, and --package-dir, the file or directory you’re linking to. Upon encountering a path conflict, Guile-Stash prompts the user to choose between overwriting the existing file or skipping the symlink creation, ensuring intentional and informed actions are taken.

Key Features:

  • Easy command-line argument parsing for specifying source and target paths.
  • Interactive conflict resolution: users can choose to overwrite or skip on a case-by-case basis.
  • Support for both file and directory symlinks.
  • Built with the robustness and flexibility of Guile Scheme.

Why Guile-Stash?

In my workflow, I often encountered the need to manage symlinks, sometimes leading to conflicts with existing files or directories. I wanted a tool that not only automated the creation of symlinks but also provided an intuitive way to handle conflicts. Thus, Guile-Stash was born, combining the power of Scheme with practical file management capabilities.

Developed as an alternative to GNU stow, and as a project to develop my own guile scheme knowledge. My first project of any kind in the programming space.

Getting Started

To get started with Guile-Stash, clone the repository from here, and ensure you have Guile installed on your system. Use the command below for a basic operation:

bash

guile -L . guile-stash.scm --target=<target-dir> --package-dir=<package-dir>

Contributing

Guile-Stash is open for contributions! Whether it’s adding new features, improving existing ones, or fixing bugs, all contributions are welcome. Please feel free to fork the repository, make your changes, and submit a pull request.

ToDo List

While Guile-Stash is fully functional, there’s always room for improvement. Here are a few items on my ToDo list:

  • Implement verbose and quiet output modes for better user control over command feedback.
  • Add support for logging actions taken during symlink creation and conflict resolution.
  • Enhance error handling to provide more descriptive messages and recovery suggestions.
  • Explore the possibility of undo functionality for reverted actions taken by the tool.
  • Use colors to differentiate parts of the output, such as errors (red), warnings (yellow), and success messages (green).

Feedback and Suggestions

Your feedback is invaluable to making Guile-Stash even better. Please don’t hesitate to share your thoughts, suggestions, or report issues you encounter. Together, we can make Guile-Stash a robust tool for everyone in the community.

Thank you for checking out Guile-Stash. I’m looking forward to your feedback and contributions!

12 Likes

Congrats on releasing Stash, this is really exciting!

I think it’d be awesome if someone could contribute a Guix package definition for it so that it might be added to the main Guix package repo.

Nice project. Where can I send issues and patches?

I am in the process of figuring that out @qeqpep . I’ll get back to you soonest with an answer.

Thanks

Congrats on the release, @Glenneth ! It can be a bit of a scary thing to let your project out in the open, in particular the first time. Well done, you!

Ask and ye shall (almost) receive:

(define-module (guix-packager)
  #:use-module (guix)
  #:use-module ((guix licenses) #:prefix license:)
  #:use-module (gnu packages)
  #:use-module (guix build-system gnu)
  #:use-module (guix git-download))

(define-public guile-stash
  (package
    (name "guile-stash")
    (version "1.0")
    (source
      (origin
        (method git-fetch)
        (uri (git-reference
              (url "https://git.sr.ht/~glenneth/guile-stash/tree/master")
              (commit "master")))
        (file-name (git-file-name name version))
        (sha256 (base32 "1sm28xn8hm8hbw4klfrrdcybn8zk27lhrk1brph8bzcqs7s8n03k"))))
    (build-system gnu-build-system)
    (arguments (list 
                     #:test-target ""
                     #:tests? #f))
    (home-page "https://git.sr.ht/~glenneth/guile-stash/tree/master/item/guile-stash.scm")
    (synopsis "A command-line utility written in Guile Scheme for creating symbolic links (symlinks) for files and directories")
    (description "Create and manage symlinks with conflict resolution")
    (license license:gpl3+)))

;; This allows you to run guix shell -f guix-packager.scm.
;; Remove this line if you just want to define a package.
guile-stash

I used Guix Packager for this. Note: The license is incorrect; Guix Packager doesn’t seem to offer MIT and I don’t know if that’s a limitation in the guix licenses package or the Guix Packager. The license used in this package definition is GPL3+. Apart from that obvious violation, I believe this package definition should be usable?

1 Like

You can send patches or any issues to ~glenneth/guile-stash@lists.sr.ht.

I will update the readme.

Thanks

They call it expat; from licenses.scm:

;; Some people call it the MIT license. For clarification see:
;; https://www.gnu.org/licenses/license-list.html#Expat
(define expat
  (license "Expat"
           "http://directory.fsf.org/wiki/License:Expat"
           "https://www.gnu.org/licenses/license-list.html#Expat"))

I keep running into this myself.

2 Likes

Thanks! I tried asking the interwebs for answers to this. I guess taking a peek at the source files would have yielded better results :sweat_smile:

1 Like

I’ve used stow for a couple of months before switching to guix home. I liked stow’s simplicity but I did not like the fact that you had to replicate the directory structure, and with guix-home you can create the symlinked files programmatically, with I like a lot, but it involves the reconfigure step.

Could you elaborate on the specific workflow or use cases? I only have a few symlinks for external drives. It seems like an interesting project but I’m already using a dot files solution. I guess it is super useful for organizing directories, a few realistic examples would be great for illustrating this.

Some feedback just from the readme and code:

  • I like that it includes the link to the guile installation.
  • I like the interactive mode ( I will borrow this idea).
  • A bash script can be used to create an executable.
  • Maybe it could take a scm file as an argument with a description of the files to be symlinked (some guile-stash data format).
1 Like

Hey @mirkoh

It’s currently a work in progress. The end target will be to add the functionality of GNU Stow with additional features being added from users comments.

As for workflow and examples, I am working on expanding the functionality and will update the readme and additional documentation as the project progresses.

Your suggestions of using a bash script to execute and taking a .scm file as an argument is interesting and definitely worth investigating.

As the project develops I will be posting about it here.

Thanks.

Just in case you’re interested, @Glenneth , stow needs a new co-maintainer.

1 Like

Hey @paulwicking

I appreciate the heads-up. stow is written in Perl and I know nothing of Perl lol.

I have just pushed an update to the dev branch of guile-stash though

guile-stash

Check it out. I’d be interested in anyone’s feedback or suggestions.

Cheers.

2 Likes

guix-home has home-dotfiles-service-type which links files according to stow algorithm. Also written in guile. It’s not an identical solution since its using guix file service to create the links, but thought you might be interested.

1 Like

Definitely @moto

Thanks. I’ll take a look

Cheers

Announcing Guile-Stash Version 1.1: Enhanced Features and Improvements

Greetings everyone,

I’m excited to share the updated version of Guile-Stash, a command-line utility designed to streamline the creation and management of symbolic links (symlinks) for files and directories. The original version 1.0 provided a robust foundation for symlink management with features such as command-line argument parsing, conflict detection, and user resolution options. However, with the release of version 1.1, we have introduced several enhancements to improve functionality and user experience.

Here are the key differences and improvements in Guile-Stash 1.1 compared to version 1.0:

1. Compatibility Update:

  • Original: Guile 2.2+
  • Updated: Guile 3.0.9
    • Improvement: Ensures compatibility with the latest version of Guile, taking advantage of new features and optimizations available in Guile 3.0.9.

2. ANSI Color Coding for Terminal Output:

  • New Feature: Added ANSI color codes for terminal output to enhance readability and user experience.
    • Implementation: Defined color codes for red, yellow, green, and reset. Messages are now wrapped in color functions to highlight different types of messages (e.g., errors in red, prompts in yellow, success messages in green).

3. Shell Quoting for Arguments:

  • New Feature: Added a function to handle shell quoting of arguments containing spaces.
    • Implementation: The shell-quote-argument function ensures that arguments with spaces are correctly quoted, preventing issues with system command execution.

4. Delete Directory Function:

  • New Feature: Introduced a function to recursively delete directories.
    • Implementation: The delete-directory function uses system commands to remove directories, complementing the existing file deletion functionality.

5. Enhanced Conflict Resolution:

  • Original: Options to overwrite or skip on conflict.
  • Updated: Added an option to rename on conflict.
    • Implementation: The prompt-user-for-action function now includes an option to rename the existing file or directory in case of a conflict. This provides more flexibility in handling conflicts.

6. Improved Error Handling:

  • New Feature: Enhanced error handling using catch for system errors during symlink creation.
    • Implementation: The create-symlink function now catches system errors, providing a user-friendly message if a symlink cannot be created due to existing files.

7. User Interface Enhancements:

  • Original: Plain text messages.
  • Updated: Color-coded messages for better readability and user interaction.
    • Implementation: Functions like color-message are used to display messages in different colors based on their context (e.g., errors, prompts, success).

Summary of Usage:

The usage remains consistent with the original version:

guile -L . guile-stash.scm --target=<target-dir> --package-dir=<package-dir>

Replace <target-dir> with the directory where you want the symlink(s) to be created, and <package-dir> with the path to the source file or directory.

Conclusion

These enhancements make Guile-Stash 1.1 a more robust and user-friendly tool for managing symlinks. The added functionalities and improved error handling are aimed at providing a seamless experience for users.

Of course this is a work in progress.

I hope you find these updates useful. As always, I welcome your feedback and suggestions for further improvements.

Cheers

1 Like

Update: Major Changes and Fixes to Guile-Stash (Now Named “Stash”)

Hi everyone,

I wanted to share an update on my Guile Scheme project, Stash (previously named Guile-Stash), along with some of the challenges and fixes I’ve worked through today. The project is still in its experimental phase, and I’ve made several improvements to both functionality and usability.

You can find the latest code hosted on Codeberg here.

Key Changes:

Name Change and Versioning
The project is now called Stash to reflect its more general-purpose function of moving directories and creating symlinks. I've also updated the versioning system to follow semantic versioning, and the current version is 0.1.0-alpha.1.

Improved Conflict Resolution
One of the biggest improvements is how Stash handles conflicts. Now, if a directory or symlink already exists, the user is prompted to:
    Overwrite the existing directory or symlink
    Backup the directory (renaming it with a timestamp)
    Skip the operation
    Cancel the operation

Example conflict prompt:

scss
A conflict was detected. Choose action - Overwrite (o), Backup (b), Skip (s), or Cancel (c):

Backup Functionality
If the user chooses to back up the existing directory, the program renames it to include a timestamp (e.g., test.backup.2024-09-22-14-20-09). This ensures no data is lost, while also allowing the creation of the new symlink or directory.

Symlink Creation After Backup
After the directory is backed up, Stash automatically recreates the symlink in the source directory, ensuring the original functionality remains intact.

Switched from rename-file to copy-recursively
Initially, I encountered errors when trying to move directories using rename-file. This has been resolved by switching to copy-recursively, allowing for safe directory operations and ensuring that all contents are moved properly.

Challenges and Workarounds:

"Is a Directory" Error:
Early on, I also encountered errors when trying to move directories using rename-file. The solution was to switch to copy-recursively to handle directories more effectively. This ensures that all contents of the directory are properly moved before any symlink operations are carried out.

Handling Existing Symlinks:
Another tricky issue was handling conflicts when a symlink already exists. The program now handles these conflicts gracefully, with the user being prompted to take action (overwrite, backup, etc.).

Unbound Variable Errors:
I also ran into unbound variable issues, specifically with delete-directory, shell-quote-argument, and file-is-symlink?. These were addressed by ensuring that the appropriate modules and helper functions were included in the code.

What’s Next?

Further Testing:
There’s still more testing needed, especially for edge cases involving larger directories and nested symlinks. The error-handling mechanisms are in place, but any feedback from the community would be extremely helpful in finding any remaining bugs.

Additional Features:
I’m considering adding more non-interactive options for automating workflows (e.g., a --force flag to always overwrite or a --dry-run flag to simulate the process).

Thanks for all the support so far! Feel free to check out the code on Codeberg, and I look forward to hearing your thoughts on these updates.

Have a great day o7

1 Like

The MIT license in GUIX is called expat

1 Like

I should change it to the GPL @snamellit :smiley:

1 Like

Update: Stash - Evolution and Improvements

Hi everyone,

I wanted to share an exciting update about Stash (formerly known as Guile-Stash). The project has matured significantly since my last update, and I’m happy to report several improvements and refinements.

You can find the project at: Stash on Codeberg

Key Improvements:

  1. Simplified Naming
    The project is now simply called “Stash”, making it more concise and reflecting its maturity as a general-purpose tool for directory management and symlink creation in Scheme.

  2. Enhanced Stability
    The core functionality has been thoroughly tested and refined, particularly around:

  • Directory movement operations
  • Symlink handling
  • Conflict resolution
  • Backup procedures
  1. Robust Error Handling
    The error handling system has been further improved, providing clearer feedback and more graceful recovery from edge cases.

  2. Documentation
    The project documentation has been enhanced to make it more accessible for new users and to better explain the various features and options.

What’s Next:
I’m continuing to refine the codebase and welcome community feedback. The project remains open source and available on Codeberg for anyone interested in contributing or trying it out.

Thanks for your continued support and interest in the project!

Have a great day o7

1 Like