Is there a "VCS" where each version update is an arbitrary script

For discussions about programming, and for programming questions and advice


Moderator: Forum moderators

Post Reply
disciple
Posts: 18
Joined: Fri Dec 18, 2020 5:54 am

Is there a "VCS" where each version update is an arbitrary script

Post by disciple »

Hi guys, I was thinking of writing a very simple script to do version control, but not as we know it.

The idea is to store a version number in a file. The changes in each version will be defined by an manually created script, which can do arbitrary things - install software, create, delete or edit files - whatever.
The version control script will simply check the current version number, see if any later versions are available, and obtain and run the script defining each later version, until the system is up to date.
There is no need for the ability to roll-back to an older version, or update to any version other than the latest. If I manage to break something with an update, I will simply need to write a new version to fix it.

Rather than writing my own script, I thought I could just use a package management system that supports preinstall or postinstall scripts - all I would need to do is create a package for each version which just has a postinstall script that does all the work. Except I'm not sure if there is a package management system that will only upgrade one version at a time - generally they just skip to the latest available version.

I'm curious, does anybody know of an existing VCS that is "script based" like I described?

Alternatively, any particularly simple package management systems that support postinstall scripts? Any that you can force to upgrade one version at a time rather than skipping to the latest available version?

Last edited by disciple on Mon Nov 15, 2021 6:14 pm, edited 1 time in total.
jamesbond
Posts: 717
Joined: Tue Aug 11, 2020 3:02 pm
Location: The Pale Blue Dot
Has thanked: 124 times
Been thanked: 402 times

Re: Is there a "VCS" where each version update is an arbitrary script

Post by jamesbond »

disciple wrote: Mon Nov 15, 2021 11:33 am

Alternatively, any particularly simple package management systems that support postinstall scripts?

Doesn't Puppy's own petget supports post-install scripts?

disciple
Posts: 18
Joined: Fri Dec 18, 2020 5:54 am

Re: Is there a "VCS" where each version update is an arbitrary script

Post by disciple »

Yeah. But I was thinking of something that supports checking for updates to a package from the command line and installing them if available. I didn't think petget supports that, but I could be wrong.
Also I've edited my post to clarify I'm particularly interested in whether any package management system can force sequential upgrades, rather than skipping straight to the latest version, which is normally what they're intended to do.

amigo
Posts: 56
Joined: Wed Nov 03, 2021 8:06 pm
Location: Germany
Has thanked: 1 time
Been thanked: 4 times

Re: Is there a "VCS" where each version update is an arbitrary script

Post by amigo »

Umm, that actually kind sounds like slackware... where each update is a README. What would your system do about faulty builds, or how should it know which intermediate packages exist?

disciple
Posts: 18
Joined: Fri Dec 18, 2020 5:54 am

Re: Is there a "VCS" where each version update is an arbitrary script

Post by disciple »

What would your system do about faulty builds

If an update is found to have broken something, another update will need to be created to unbreak it. If it is desirable, the broken update can also be overwritten (with one that perhaps doesn't actually do anything) so that any systems where the broken update hasn't yet been applied don't have to be broken and then unbroken.
If an update breaks the update system, it will need to be fixed manually.

how should it know which intermediate packages exist

It does not check what the latest package is, it just adds 1 to the current version number, and checks if that version exists. If it does, it installs it and then adds 1 and checks again.

disciple
Posts: 18
Joined: Fri Dec 18, 2020 5:54 am

Re: Is there a "VCS" where each version update is an arbitrary script

Post by disciple »

disciple wrote: Mon Jan 10, 2022 1:33 am

If it is desirable, the broken update can also be overwritten

Of course I realise that this would generally be considered to be very bad practice - for my purposes I don't care, but now that I've thought more about it I'll probably make it also record the date and time the current version was installed, or the version checksum, so if necessary I can quickly check if a system is running a known broken version.
The alternative would be to complicate the numbering, so that a broken version 2 is replaced by a version 2.1 rather than a version 3. In that case the version checking logic would be more complicated - if we are at version 1 we will need to check for the latest available 2.x version.

disciple
Posts: 18
Joined: Fri Dec 18, 2020 5:54 am

Re: Is there a "VCS" where each version update is an arbitrary script

Post by disciple »

Proof of concept:

Code: Select all

#! /bin/bash 

# Get the script name; we will use it to store configuration/version data
# We won't bother making sure the script is safe for anything exotic like spaces in the path
SCRIPT_NAME=${0##*/} # like basename without requiring basename

# TODO: should check the updater isn't already running, and probably other things like apt (or check if apt database is locked or whatever it is that apt itself checks)

# Check which version is currently installed
read VERSION<~/.$SCRIPT_NAME/VERSION
if [[ $VERSION =~ ^[0-9]+$ ]]
then
 
 # TODO: sync directory ~/.$SCRIPT_NAME/versions with the repository
 
 # keep running updates until they are all done
 CONTINUE=1
 while [ $CONTINUE = 1 ]
 do
  CONTINUE=0
  # check if the next version update exists
  UPDATE_PATH=~/.$SCRIPT_NAME/versions/$((VERSION + 1))
  if [ -f $UPDATE_PATH ]; then
   # do the update
   source $UPDATE_PATH && VERSION=$((VERSION + 1)) && echo $VERSION>~/.$SCRIPT_NAME/VERSION && echo "version $VERSION installed at `date`">>~/.$SCRIPT_NAME/LOG && CONTINUE=1
  else
   echo "system is up to date"
  fi
 done

else
 echo "\"$SCRIPT_NAME\" updater only works if there is a whole number in ~/.$SCRIPT_NAME/VERSION"
fi

Comments?

disciple
Posts: 18
Joined: Fri Dec 18, 2020 5:54 am

Re: Is there a "VCS" where each version update is an arbitrary script

Post by disciple »

FWIW I'll probably use it at some point to administer real linux installs, but my use case at the moment is to simply administer WSL installs on multiple computers.
It is run automatically whenever a particular tool in the WSL install is used. Any time I want to change anything on all the installs I'll just need to put it in the next version script in the repository - it will automatically be copied into ~/.$SCRIPT_NAME/versions/ and then run.

User avatar
sc0ttman
Posts: 93
Joined: Sat Aug 22, 2020 3:55 pm
Has thanked: 4 times
Been thanked: 33 times

Re: Is there a "VCS" where each version update is an arbitrary script

Post by sc0ttman »

Hiya,

Hopefuly this might be of interest.

I saved this a while back. The site and script has since disappeared off the internet (preserved in my dotfiles repo though).

# CVS Lite
# A Lightweight Alternative to CVS
# by Philip Guo
# http://alum.mit.edu/www/pgbovine/

A lightweight, portable single-user version control system inspired by CVS.

It's like Git, but uses .tar files to store the repo, and diff files to manage "commits".

It's a shame the related homepage is down - it was a great walkthrough and tutorial.

It could conceivably be extended to support branches too - the homepage would have helped in that regard.

Code: Select all

#!/bin/bash

# CVS Lite
# A Lightweight Alternative to CVS
# by Philip Guo
# http://alum.mit.edu/www/pgbovine/
# Copyright 2006 Philip J. Guo

# 2006-01-06: Created
# 2006-01-10: Completed first version

# Summary: A lightweight, portable single-user version control system
#          inspired by CVS

# Requires: BASH, UNIX-like environment, preferably GNU tools (should
#           work with other versions of UNIX tools as well)

#     This program is free software; you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation; either version 2 of the License, or
#     (at your option) any later version.

#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.

# Possible new features (to be implemented whenever I feel like it)
#
# 1. Support for processing multiple files in one cvslite command
# 2. Support for renaming files after they're put in repository
# 3. Compression of repositories (e.g., gzip, bzip2)


# Programming note: Beware of name clashes because there only seems to
# be one global namespace, even for variables declared inside of
# functions.


# Sub-directory of `pwd` where repositories for all files in this
# directory are located:
CVSLITE_DIR=CVSLite

# Temporary directory where all the work takes place.  This should
# never be visible to users because it should always be deleted when
# the script exits:
CVSLITE_TMP=cvslite-tmp

# All return values are stored here in order to bypass byzantine 8-bit
# restrictions on BASH function return values
RETURN_VAL=0

E_BADARGS=65

print_usage() {

cat << END_OF_MSG

 CVS Lite, by Philip Guo <philip@pgbovine.net>

   A lightweight single-user version control system inspired by CVS.
   Repositories for each file are patches and logs stored in a tarball
   in the $CVSLITE_DIR/ sub-directory relative to the file's path.

 Usage:

   cvslite.sh <command> <optional arguments> <filename>

 Supported commands:

   add      Add file to repository if it's not already there

   commit   Save the working version as a new version in repository

   log      Print log of versions and user comments for the file

   up       Save a version of the file with the most recent
            version num. as \$FILENAME.r<version num.>

   up <version num.>    Save a version of the file with the given
                        version num. as \$FILENAME.r<version num.>

   diff                 Compare the working version with the most
                        recent version

   diff <version num.>  Compare the working version with the version
                        with the given version num.

   diff <version num. 1> <version num. 2>  Compare two versions of file

 Version num. format:
   -r<num> where <num> is a non-negative integer (e.g., -r0 -r1 -r2 -r3)
           (Do not use a decimal point in version num.)
END_OF_MSG

}


# Returns -1 for invalid version_num, version num. for valid version
# Bug: This will treat "0010" as a separate number than "10" - it does
# not trim leading zeroes.
get_version_num() {
    VERSION_NUM="$1"
    VERSION_NUM=${VERSION_NUM#-r}

    # Truncate everything except numerical digits off of VERSION_NUM
    # and compare it with original
    TRUNC_NUM=`echo $VERSION_NUM | tr -dc [:digit:]`

    if [ $VERSION_NUM != $TRUNC_NUM ]
    then
	RETURN_VAL=-1
    else
	RETURN_VAL=$VERSION_NUM
    fi
}


# Returns version X (passed in as $2 - must be a valid integer or
# "newest") of the file (passed in as $1) in $FILENAME.patching and
# the version number of the version after X in the global var
# $RETURN_VAL (useful for 'commit' to determine the lowest unused
# version number) or returns -1 if X ($2) does not exist in repository
# If $2 == "newest", then return the newest version in the repository
# Pre: We have unpacked the tar file representing the repository in
# $CVSLITE_TMP and we have already switched into $CVSLITE_TMP
return_file_version() {
    FILENAME="$1"
    MAX_VERSION="$2"

    # Apply all patches to $FILENAME.r0 (which is the original file)
    # to get to the most recent version, using the temporary file
    # $FILENAME.patching as the targets of all the intermediate
    # patches:

    # We need to apply the patches numerically, NOT lexicographically
    # (e.g., r2 must come before r12, even though it is
    # lexicographically earlier)

    if [ $MAX_VERSION = "0" ]
    then
	cp $FILENAME $FILENAME.patching # Special case for r0
    else
	ln -s $FILENAME.r0 $FILENAME.patching
    fi

    VERSION_NUM=1
    FOUND=0

    if [ $MAX_VERSION = "newest" ]
    then
	FOUND=1
    fi

    while [ -e $FILENAME.r$VERSION_NUM.diff ]
    do
	if  (($FOUND == 0)) && (($VERSION_NUM > $MAX_VERSION))
	then
	    FOUND=1
	    break
	fi

	# Only perform a patch if the diff file is not empty:
	if [ -s $FILENAME.r$VERSION_NUM.diff ]
	then
	    # Possible future optimization: Avoid using the '-o' to
	    # make a copy of the file; instead, use the default
	    # behavior of patch to make the changes to the file
	    # inline to avoid file copying overhead

	    ln -s $FILENAME.patching $FILENAME.r$VERSION_NUM

	    patch -i $FILENAME.r$VERSION_NUM.diff -o $FILENAME.patching.tmp > /dev/null
	    rm $FILENAME.patching
	    mv $FILENAME.patching.tmp $FILENAME.patching

	    rm $FILENAME.r$VERSION_NUM
	fi

	VERSION_NUM=$(($VERSION_NUM+1))
    done

    # One more chance to be found:
    if (($VERSION_NUM == $MAX_VERSION + 1))
    then
	FOUND=1
    fi

    if (($FOUND == 1))
    then
	RETURN_VAL=$VERSION_NUM
    else
	RETURN_VAL=-1
    fi

}


# Common prologue for most operations
# Returns -1 (in $RETURN_VAL) for error, 0 for success (and pushd into
# $CVSLITE_TMP on success)
# Args: FILENAME="$1"
common_prologue() {
    FILENAME="$1"

    if ! [ -e $FILENAME ]
    then
	echo Error! File \'$FILENAME\' does not exist.
	RETURN_VAL=-1
	return
    fi

    REPOSITORY=$CVSLITE_DIR/$FILENAME.cvslite.tar

    if ! [ -d $CVSLITE_DIR ] || ! [ -e $REPOSITORY ]
    then
	echo Error! File \'$FILENAME\' is not in CVS Lite repository.
	RETURN_VAL=-1
	return
    fi

    # Do all of the work in $CVSLITE_TMP.
    if  [ -d $CVSLITE_TMP ]
    then
	rm -rf $CVSLITE_TMP
    fi

    mkdir $CVSLITE_TMP
    pushd $CVSLITE_TMP > /dev/null

    # Alias the original version as .r0
    ln -s $FILENAME $FILENAME.r0
}

# Common epilogue for success (only run if common_prologue returned 0)
common_epilogue() {
    popd > /dev/null

    # Clean-up
    rm -rf $CVSLITE_TMP
}


# The core workhorse functions:

# Creates a $FILENAME.cvslite.tar file in $CVSLITE_DIR to represent
# the archive.  Add the file represented by $FILENAME, a log file
# $FILENAME.r0.log, as well as an info file $FILENAME.cvslite to the
# archive.  $FILENAME.cvsinfo contains metadata such as the current
# version number, etc... - support for this has not yet been
# implemented
handle_add() {
    FILENAME="$1"

    if ! [ -e $FILENAME ]
    then
	echo Error! File \'$FILENAME\' does not exist.
	return
    fi

    REPOSITORY=$CVSLITE_DIR/$FILENAME.cvslite.tar

    if ! [ -d $CVSLITE_DIR ]
    then
	mkdir $CVSLITE_DIR
    fi

    if [ -e $REPOSITORY ]
    then
	echo Error! File \'$FILENAME\' is already in CVS Lite repository.
	return
    fi

    # Prompt the user to write a log message using vi
    touch $FILENAME.r0.log
    vi $FILENAME.r0.log

    # Empty log file - have a chance to abort
    if ! [ -s $FILENAME.r0.log ]
    then
	choice="blah"
	while ! [ $choice = "a" ] && ! [ $choice = "c" ]
	do
	    echo "Empty log file: (a)bort or (c)ontinue"
	    read choice
	    if [ $choice = "a" ]
	    then
		# Clean-up and return
		popd > /dev/null

		echo "Add operation aborted"

		# Clean-up
		rm -rf $CVSLITE_TMP

		return
	    fi
	done
    fi

    tar -cf $CVSLITE_DIR/$FILENAME.cvslite.tar $FILENAME $FILENAME.r0.log > /dev/null
    echo File \'$FILENAME\' added to CVS Lite repository.

    rm $FILENAME.r0.log
}


# Find all log files within $FILENAME.cvslite.tar ($FILENAME.r*.log)
# and cat contents
handle_log() {
    FILENAME="$1"

    common_prologue $FILENAME
    if (($RETURN_VAL == -1))
    then
	exit $E_BADARGS
    fi

    # Extract only the log files (*.log) from archive
    tar -xf ../$REPOSITORY *.log > /dev/null

    echo
    echo "CVS Lite log for file '$FILENAME'"

    # Print out 0th version - original
    echo "----------------------------------------"
    echo "Version 0:  `date -r $FILENAME.r0.log`" # Does date -r only work with GNU date?
    echo
    echo "  [Original file]"
    echo

    VERSION_NUM=1
    while [ -e $FILENAME.r$VERSION_NUM.log ]
    do
	echo "----------------------------------------"
	echo "Version $VERSION_NUM:  `date -r $FILENAME.r$VERSION_NUM.log`"
	echo

	if [ -s $FILENAME.r$VERSION_NUM.log ]
	then
	    cat $FILENAME.r$VERSION_NUM.log
	else
	    echo "  [No log entry]"
	fi

	echo

	VERSION_NUM=$(($VERSION_NUM+1))
    done

    common_epilogue
}


# Open vi to write a new log entry, then save it as a log file within
# $FILENAME.cvslite.tar.  Perform a diff from the previous version and
# save patch within $FILENAME.cvslite.tar.  Each patch file should be
# named $FILENAME.r$VERSION_NUM.diff.  Each log file should be named
# $FILENAME.r$VERSION_NUM.log where $VERSION_NUM is the current
# version number (positive integer).  On success, this function adds 2
# files to $FILENAME.cvslite.tar.
handle_commit() {
    FILENAME="$1"

    common_prologue $FILENAME
    if (($RETURN_VAL == -1))
    then
	exit $E_BADARGS
    fi

    # Extract archive contents in tmp directory
    # (Possible optimization: Do not need to extract log entries)
    tar -xf ../$REPOSITORY > /dev/null

    # Grab the newest version of the file in $FILENAME.patching
    return_file_version $FILENAME "newest"

    # Now VERSION_NUM should be set to the lowest unused version
    # number (the return value of return_file_version()).  Create a
    # patch against the current working version of the file:
    VERSION_NUM=$RETURN_VAL

    ln -s ../$FILENAME $FILENAME.r$VERSION_NUM

#    echo diff -u $FILENAME.patching $FILENAME.r$VERSION_NUM redirect to $FILENAME.r$VERSION_NUM.diff

    diff -u $FILENAME.patching $FILENAME.r$VERSION_NUM > $FILENAME.r$VERSION_NUM.diff

    # If there are no diffs, then abort
    if ! [ -s $FILENAME.r$VERSION_NUM.diff ]
    then
	echo "No diffs to commit for '$FILENAME'"
	# Clean-up and return
	common_epilogue
	return
    fi

    # Prompt the user to write a log message using vi
    touch $FILENAME.r$VERSION_NUM.log
    vi $FILENAME.r$VERSION_NUM.log

    # Empty log file - have a chance to abort
    if ! [ -s $FILENAME.r$VERSION_NUM.log ]
    then
	choice="blah"
	while ! [ $choice = "a" ] && ! [ $choice = "c" ]
	do
	    echo "Empty log file: (a)bort or (c)ontinue"
	    read choice
	    if [ $choice = "a" ]
	    then
		# Clean-up and return
		popd > /dev/null

		echo "Commit operation aborted"

		# Clean-up
		rm -rf $CVSLITE_TMP

		return
	    fi
	done
    fi

    # Add new patch file to the archive
    tar --file ../$REPOSITORY --append $FILENAME.r$VERSION_NUM.diff

    # Add the log message to the archive
    tar --file ../$REPOSITORY --append $FILENAME.r$VERSION_NUM.log

    echo Committed version $VERSION_NUM of \'$FILENAME\'

    # Clean-up
    common_epilogue
}

# Generates VERSION_NUM ($1) of the file as $FILENAME.r$VERSION_NUM
# If $1 == "newest", grab the latest version
handle_up() {
    UP_VERSION_NUM="$1"
    FILENAME="$2"

    if ! [ $UP_VERSION_NUM = "newest" ]
    then
	get_version_num $UP_VERSION_NUM
	UP_VERSION_NUM=$RETURN_VAL

	if (( $UP_VERSION_NUM == -1 ))
	then
	    echo "Error! $1 is an invalid version number."
	    exit $E_BADARGS
	fi
    fi

    common_prologue $FILENAME
    if (($RETURN_VAL == -1))
    then
	exit $E_BADARGS
    fi

    # Extract archive contents in tmp directory
    # (Possible optimization: Do not need to extract log entries)
    tar -xf ../$REPOSITORY > /dev/null

    # Grab the specified version of the file in $FILENAME.patching
    return_file_version $FILENAME $UP_VERSION_NUM

    if (($RETURN_VAL == -1))
    then
	echo "Error! Version $UP_VERSION_NUM of file '$FILENAME' does not exist."
	common_epilogue
	return
    fi

    # Get the latest saved version number:
    if [ $UP_VERSION_NUM = "newest" ]
    then
        UP_VERSION_NUM=$(($RETURN_VAL-1))
    fi

    # Move it to $FILENAME.r$UP_VERSION_NUM (not in the tmp directory):
    mv $FILENAME.patching ../$FILENAME.r$UP_VERSION_NUM

    common_epilogue

    echo "Version $UP_VERSION_NUM of file '$FILENAME' extracted as $FILENAME.r$UP_VERSION_NUM"
}


# Diffs a version of the file in the repository with the current
# working version.  If $1 == "newest", then get the newest version
handle_diff_working_version() {
    OLD_VERSION_NUM="$1"
    FILENAME="$2"

    if ! [ $OLD_VERSION_NUM = "newest" ]
    then
	get_version_num $OLD_VERSION_NUM
	OLD_VERSION_NUM=$RETURN_VAL

	if (( $OLD_VERSION_NUM == -1 ))
	then
	    echo "Error! $1 is an invalid version number."
	    exit $E_BADARGS
	fi
    fi

    common_prologue $FILENAME
    if (($RETURN_VAL == -1))
    then
	exit $E_BADARGS
    fi

    # Extract archive contents in tmp directory
    # (Possible optimization: Do not need to extract log entries)
    tar -xf ../$REPOSITORY > /dev/null

    # Grab the specified version of the file in $FILENAME.patching
    return_file_version $FILENAME $OLD_VERSION_NUM

    if (($RETURN_VAL == -1))
    then
	echo "Error! Version $OLD_VERSION_NUM of file '$FILENAME' does not exist."
	common_epilogue
	return
    fi

    # Get the latest saved version number:
    if [ $OLD_VERSION_NUM = "newest" ]
    then
	OLD_VERSION_NUM=$(($RETURN_VAL-1))
    fi

    mv $FILENAME.patching $FILENAME.r$OLD_VERSION_NUM.for-diff
    
    popd > /dev/null

    ln -s $CVSLITE_TMP/$FILENAME.r$OLD_VERSION_NUM.for-diff $FILENAME.r$OLD_VERSION_NUM.for-diff

    echo "CVS Lite diff for '$FILENAME': Version $OLD_VERSION_NUM vs. working version"
    echo
    diff -u $FILENAME.r$OLD_VERSION_NUM.for-diff $FILENAME

    # Clean-up
    rm $FILENAME.r$OLD_VERSION_NUM.for-diff
    rm -rf $CVSLITE_TMP
}


# Diffs two versions of the file in the repository
handle_diff() {
    VERSION_NUM_1="$1"
    VERSION_NUM_2="$2"
    FILENAME="$3"

    get_version_num $VERSION_NUM_1
    VERSION_NUM_1=$RETURN_VAL

    if (( $VERSION_NUM_1 == -1 ))
    then
	echo "Error! $1 is an invalid version number."
	exit $E_BADARGS
    fi

    get_version_num $VERSION_NUM_2
    VERSION_NUM_2=$RETURN_VAL

    if (( $VERSION_NUM_2 == -1 ))
    then
	echo "Error! $2 is an invalid version number."
	exit $E_BADARGS
    fi

    common_prologue $FILENAME
    if (($RETURN_VAL == -1))
    then
	exit $E_BADARGS
    fi

    # Extract archive contents in tmp directory
    # (Possible optimization: Do not need to extract log entries)
    tar -xf ../$REPOSITORY > /dev/null

    ln -s $FILENAME.r0 $FILENAME.r0.for-diff

    # Grab the specified version of the file in $FILENAME.patching
    return_file_version $FILENAME $VERSION_NUM_1

    if (($RETURN_VAL == -1))
    then
	echo "Error! Version $VERSION_NUM_1 of file '$FILENAME' does not exist."
	common_epilogue
	return
    fi

    mv $FILENAME.patching $FILENAME.r$VERSION_NUM_1.for-diff


    # Grab the specified version of the file in $FILENAME.patching
    return_file_version $FILENAME $VERSION_NUM_2

    if (($RETURN_VAL == -1))
    then
	echo "Error! Version $VERSION_NUM_2 of file '$FILENAME' does not exist."
	common_epilogue
	return
    fi

    mv $FILENAME.patching $FILENAME.r$VERSION_NUM_2.for-diff

    
    echo "CVS Lite diff for '$FILENAME': Version $VERSION_NUM_1 vs. Version $VERSION_NUM_2"
    echo
    diff -u $FILENAME.r$VERSION_NUM_1.for-diff $FILENAME.r$VERSION_NUM_2.for-diff

    # Clean-up
    common_epilogue
}


# Start of script execution:

# Parse arguments

if (( $# < 2 )) # Need at least 2 arguments: command and filename
then
    if (($# > 0))
    then
	echo "Error! CVS Lite needs at least 2 arguments."
    fi

    print_usage
    exit $E_BADARGS
fi


if [[ $1 == 'add' ]]
then
    if (( $# != 2 ))
    then
	echo "Error! Only need 1 filename for 'add' and nothing else."
	print_usage
	exit $E_BADARGS
    fi
    handle_add $2
elif [[ $1 == 'commit' ]]
then
    if (( $# != 2 ))
    then
	echo "Error! Only need 1 filename for 'commit' and nothing else."
	print_usage
	exit $E_BADARGS
    fi
    handle_commit $2
elif [[ $1 == 'log' ]]
then
    if (( $# != 2 ))
    then
	echo "Error! Only need 1 filename for 'log' and nothing else."
	print_usage
	exit $E_BADARGS
    fi
    handle_log $2
elif [[ $1 == 'up' ]]
then
    if (( $# != 2 )) && (( $# != 3 ))
    then
	echo "Error! Need 1 filename and 0 or 1 version num. arguments for 'up'"
	print_usage
	exit $E_BADARGS
    fi

    if (($# == 2))
    then
	handle_up "newest" $2
    else
	handle_up $2 $3
    fi

elif [[ $1 == 'diff' ]]
then
    if (( $# != 2 )) && (( $# != 3 )) && (( $# != 4 ))
    then
	echo "Error! Need 1 filename and either 0, 1, or 2 version num. arguments for 'diff'"
	print_usage
	exit $E_BADARGS
    fi

    if (($# == 2))
    then
	handle_diff_working_version "newest" $2
    elif (($# == 3))
    then
	handle_diff_working_version $2 $3
    elif (($# == 4))
    then
	handle_diff $2 $3 $4
    fi
else
    echo "Error! Invalid first argument: $1"
    print_usage
    exit $E_BADARGS
fi

User avatar
sc0ttman
Posts: 93
Joined: Sat Aug 22, 2020 3:55 pm
Has thanked: 4 times
Been thanked: 33 times

Re: Is there a "VCS" where each version update is an arbitrary script

Post by sc0ttman »

Or this?

https://git.sr.ht/~sircmpwn/shit

Git in POSIX Shell.. You could hack it to your needs.

User avatar
sc0ttman
Posts: 93
Joined: Sat Aug 22, 2020 3:55 pm
Has thanked: 4 times
Been thanked: 33 times

Re: Is there a "VCS" where each version update is an arbitrary script

Post by sc0ttman »

Sorry, one more..

Shiv..

Unlike "CVS Lite" it has branches, staging, and is generally more "modern" and "git-like" in its features.

Also has a nice walkthrough.

https://shatterealm.netlify.app/program ... uild_a_vcs

disciple
Posts: 18
Joined: Fri Dec 18, 2020 5:54 am

Re: Is there a "VCS" where each version update is an arbitrary script

Post by disciple »

Yeah, I like that last link.

Actually, I think it was misleading of me to talk about a "VCS" in the title (and even the version scripts don't actually need to be in a VCS).
It isn't a package manager either.
I literally called it `updater`, but maybe system administrators have a technical term for this sort of tool?

disciple
Posts: 18
Joined: Fri Dec 18, 2020 5:54 am

Re: Is there a "VCS" where each version update is an arbitrary script

Post by disciple »

sc0ttman wrote: Mon Aug 15, 2022 1:36 am

Sorry, one more..

Shiv..

Unlike "CVS Lite" it has branches, staging, and is generally more "modern" and "git-like" in its features.

Also has a nice walkthrough.

https://shatterealm.netlify.app/program ... uild_a_vcs

Link is now dead, but available at https://web.archive.org/web/20210102063 ... uild_a_vcs
Code is at https://git.sr.ht/shakna/shiv75

Post Reply

Return to “Programming”