SRCS – diff

I am writing a script to simulate a Version Control System.
In SRCS – Check in file – It implements the initial and check in a file.
In SRCS – check out file – It implements check out a file with a specified version.
In SRCS – log – It implements a ‘log’ command to allow user to print all the metadata for a file.

In this post I will implement a diff command lists file changes.

For example,
The following command will provide a list of differences between file admin/sql/test1.sql revisions 5 and 6:
srcs diff admin/sql/test1.sql 5 6
The following example, you receive a list of differences between revision 5 and the local copy:
srcs diff admin/sql/test1.sql 5


_PROD="/u01/camel/12.0"
_DEBUG="on"
_LOG="_srcs.log"

fname_srcs="$_PROD/$2"
fname=$(basename "${fname_srcs}")
fdir=`echo "${fname_srcs}" | sed 's/'"$fname"'$//'`
fver="$fdir/RCS/${fname},v"
	
function DEBUG()
{
	[ "$_DEBUG" == "on" ] && $@ || :
}

function checkout()
{
	version=`tail -3 $fver | egrep "^version#" | sed 's/^version#//'`
	cp $fname_srcs ${fname}.tmp.$1
	for (( v=$version; v>$1; v-- ))
	do
		let delta=$v-1
		_l1=`nl "$fver" | egrep "version#$delta" | sed "s/version#$delta//" | sed 's/^\s*|\s*$//g'`
		_l2=`nl "$fver" | egrep "version#$v" | sed "s/version#$v//" | sed 's/^\s*|\s*$//g'`
		sed -n "${_l1},${_l2}p" "$fver" | patch ${fname}.tmp.$1 -i - >> /dev/null
	done
}

if [ $1 == "diff" ]; then
	echo "Diff $2 $3 $4 from SRCS..." | tee -a $_LOG
	if [ "$#" -lt 3 ]; then
		echo "Please provide at least one revision for diff...<FAILED>" | tee -a $_LOG
		exit 1
	fi
	if [ ! -f "$fver" ]; then
		echo "$fname doesn't exist in SRCS...<FAILED>" | tee -a $_LOG
		exit 1
	else
		if egrep -v "^\s*$" $fver | wc -l | egrep "^0" > /dev/null ; then 
			echo "$fname is just initialled in SRCS...<FAILED>" | tee -a $_LOG
			exit 1
		else
			if ! cat $fver | egrep "^version#$3" > /dev/null ; then
				echo "Version $3 doesn't exist...<FAILED>" | tee -a $_LOG
				exit 1
			else
				checkout $3
			fi
		fi
		if [ "$#" -lt 4 ]; then 	
			echo "Diff $2 $3 from SRCS with the local copy..." | tee -a $_LOG
			if [ ! -f "$fname" ]; then
				echo "$fname doesn't exist in local directory...<FAILED>" | tee -a $_LOG
				exit 1
			fi
			diff ${fname}.tmp.$3 $fname | tee -a $_LOG
			echo "Diff $2 $3 from SRCS with the local copy...<SUCCESSED>" | tee -a $_LOG
		else 
			if ! cat $fver | egrep "^version#$4" > /dev/null ; then
				echo "Version $4 doesn't exist...<FAILED>" | tee -a $_LOG
				exit 1
			fi
			checkout $4
			diff ${fname}.tmp.$3 ${fname}.tmp.$4 | tee -a $_LOG
			echo "Diff $2 $3 $4 from SRCS...<SUCCESSED>" | tee -a $_LOG
		fi
	fi
fi

Test Result:

-bash-3.2$ sh srcs.sh diff admin/sql/test2.sql
Diff admin/sql/test2.sql   from SRCS...
Please provide at least one revision for diff...<FAILED>
-bash-3.2$ sh srcs.sh diff admin/sql/test1.sql
Diff admin/sql/test1.sql   from SRCS...
Please provide at least one revision for diff...<FAILED>
-bash-3.2$ sh srcs.sh diff admin/sql/test2.sql
Diff admin/sql/test2.sql   from SRCS...
Please provide at least one revision for diff...<FAILED>
-bash-3.2$ sh srcs.sh diff admin/sql/test2.sql 3
Diff admin/sql/test2.sql 3  from SRCS...
test2.sql is just initialled in SRCS...<FAILED>
-bash-3.2$ sh srcs.sh diff admin/sql/test2.sql 3 5
Diff admin/sql/test2.sql 3 5 from SRCS...
test2.sql is just initialled in SRCS...<FAILED>
-bash-3.2$ sh srcs.sh diff admin/sql/test1.sql 6
Diff admin/sql/test1.sql 6  from SRCS...
Diff admin/sql/test1.sql 6 from SRCS with the local copy...
2,7c2,3
<  I am Version 6
< ahoghgoh
< gegoruaon
<  hello version6
< haxialg xn
< this line is new in version 6
---
> ### I am Version 1
> ### This line should be the same
Diff admin/sql/test1.sql 6 from SRCS with the local copy...<SUCCESSED>
-bash-3.2$ sh srcs.sh diff admin/sql/test1.sql 5
Diff admin/sql/test1.sql 5  from SRCS...
Diff admin/sql/test1.sql 5 from SRCS with the local copy...
2,5c2,3
<  I am Version 5
<  hello version5
< haxialg xn
< this line is new in version 5
---
> ### I am Version 1
> ### This line should be the same
Diff admin/sql/test1.sql 5 from SRCS with the local copy...<SUCCESSED>
-bash-3.2$ sh srcs.sh diff admin/sql/test1.sql 53
Diff admin/sql/test1.sql 53  from SRCS...
Version 53 doesn't exist...<FAILED>
-bash-3.2$ sh srcs.sh diff admin/sql/test1.sql 3
Diff admin/sql/test1.sql 3  from SRCS...
Diff admin/sql/test1.sql 3 from SRCS with the local copy...
2,4c2,3
<  I am Version 3
< ### This line should be the different
< this line is new in version 3
---
> ### I am Version 1
> ### This line should be the same
Diff admin/sql/test1.sql 3 from SRCS with the local copy...<SUCCESSED>
-bash-3.2$ sh srcs.sh diff admin/sql/test1.sql 2
Diff admin/sql/test1.sql 2  from SRCS...
Diff admin/sql/test1.sql 2 from SRCS with the local copy...
2c2
< ### I am Version 2
---
> ### I am Version 1
4d3
< this line is new in version 2
Diff admin/sql/test1.sql 2 from SRCS with the local copy...<SUCCESSED>
-bash-3.2$ sh srcs.sh diff admin/sql/test1.sql 1
Diff admin/sql/test1.sql 1  from SRCS...
Diff admin/sql/test1.sql 1 from SRCS with the local copy...
Diff admin/sql/test1.sql 1 from SRCS with the local copy...<SUCCESSED>
-bash-3.2$ sh srcs.sh diff admin/sql/test1.sql 6 4
Diff admin/sql/test1.sql 6 4 from SRCS...
2,7c2,4
<  I am Version 6
< ahoghgoh
< gegoruaon
<  hello version6
< haxialg xn
< this line is new in version 6
---
>  I am Version  4
>  hello version4
> this line is new in version 4
Diff admin/sql/test1.sql 6 4 from SRCS...<SUCCESSED>
-bash-3.2$

SRCS – log

I am writing a script to simulate a Version Control System.
In SRCS – Check in file – It implements the initial and check in a file.
In SRCS – check out file – It implements check out a file with a specified version.

In this post I will implement a ‘log’ command to allow user to print all the metadata for a file, including a complete version history and the checkin comments.


_PROD="/u01/camel/12.0"
_DEBUG="on"
_LOG="_srcs.log"

fname_srcs="$_PROD/$2"
fname=$(basename "${fname_srcs}")
fdir=`echo "${fname_srcs}" | sed 's/'"$fname"'$//'`
fver="$fdir/RCS/${fname},v"

function DEBUG()
{
	[ "$_DEBUG" == "on" ] && $@ || :
}

if [ $1 == "log" ]; then
	echo "Log for $2 from SRCS..." | tee -a $_LOG
	if [ ! -f "$fver" ]; then
		echo "$fname doesn't exist in SRCS...<FAILED>" | tee -a $_LOG
		exit 1
	else
		if egrep -v "^\s*$" $fver | wc -l | egrep "^0" > /dev/null ; then
			echo "$fname is just initialled in SRCS and has no revision...<FAILED>" | tee -a $_LOG
		else
			logs=`cat $fver | egrep "^version#|comment"`
			echo "$logs" | tee -a $_LOG
		fi
	fi
fi

Test result:

-bash-3.2$ sh srcs.sh log admin/sql/test2.sql
Log for admin/sql/test2.sql from SRCS...
test2.sql is just initialled in SRCS and has no revision...<FAILED>
-bash-3.2$ sh srcs.sh log admin/sql/test3.sql
Log for admin/sql/test3.sql from SRCS...
test3.sql doesn't exist in SRCS...<FAILED>
-bash-3.2$ sh srcs.sh log admin/sql/test1.sql
Log for admin/sql/test1.sql from SRCS...
comment#initial checkin for test1.sql
version#1
comment#hello version 2
version#2
comment#okie, version 3
version#3
comment#i am version 4.
version#4
comment#hello hello version 5
version#5
comment#version 6 here...
version#6
-bash-3.2$

MISC – May 19th, 2014

1# nl – number lines of files. Write each FILE to standard output, with line numbers added.  With no FILE, or when FILE is -, read standard input.

-bash-3.2$ cat file1
This is file 1
I am a file 1
-bash-3.2$ nl file1
1 This is file 1
2 I am a file 1
-bash-3.2$

2# sed -n “$start,${end}p” filename
Output certain lines from a file

-bash-3.2$ nl file2
     1  This is file 2
     2  I am a file 2
     3  line 3 - 123
     4  line 4 - 123
     5  line 5 - 123
-bash-3.2$ sed -n '2,4p' file2
I am a file 2
line 3 - 123
line 4 - 123
-bash-3.2$

3# In Shell, if you want to pass variables into a pattern, the best practice is to use a double quotes instead of the single ones, so the $variables can be expanded.

-bash-3.2$ export start=2
-bash-3.2$ export end=4
-bash-3.2$ sed -n '$start,${end}p' file2
sed: -e expression #1, char 14: unterminated `s' command
-bash-3.2$ sed -n "$start,${end}p" file2
I am a file 2
line 3 - 123
line 4 - 123
-bash-3.2$

4# Three typical ways to do for in Shell,

for (( v=10; v>1; v-- ))
do

done

for i in {1..5}
do
   echo "Welcome $i times"
done

for f in $FILES
do

done

5# Output all of the lines except the last N lines.

head -n -N file
-bash-3.2$ nl file2
1 This is file 2
2 I am a file 2
3 line 3 - 123
4 line 4 - 123
5 line 5 - 123
-bash-3.2$ head -n -2 file2
This is file 2
I am a file 2
line 3 - 123
-bash-3.2$
6# output all of the lines except the first N lines.
<pre>
tail -n +(N+1) file
-bash-3.2$ nl file2
1 This is file 2
2 I am a file 2
3 line 3 - 123
4 line 4 - 123
5 line 5 - 123
-bash-3.2$ tail -n +3 file2
line 3 - 123
line 4 - 123
line 5 - 123
-bash-3.2$

SRCS – check out file

I just started up writing a script to simulate a basic Source Version Control tool. In http://luohuahuang.com/2014/05/17/srcs-startup/ I prepared an experimental script to do initial and checkin activities. Now in this post I will try the check out function.
Basically the check out function will support:
1# If the version is the latest, just copy the latest from repository to local.
2# otherwise check out the specified version.

I will use Linux patch command to apply the diff content to the latest file to get the specified version.
The logic:
1# copy the latest file to local.
2# run patch command to apply diff in a loop way until it reaches the specified version. For example,

-bash-3.2$ cat 2.sql
hello world
no wrong v4
new line in v4
select * from table2;
-bash-3.2$ vi diff.txt
-bash-3.2$ cat diff.txt | patch 2.sql -i -
patching file 2.sql
-bash-3.2$ cat 2.sql
hello world
no wrong
new line in v3
select * from table2;

Note:
-i patchfile or –input=patchfile
Read the patch from patchfile. If patchfile is -, read from standard input, the default.

So in the loop, I will extract the diff content from filename,v and output it into standard input for patch command.

The logic:

1. if it checks out a file doesn’t have history in repository. Failed.

2. if it checks out the file without specifying a version or with the latest version. Check out the latest version.

3. if it chceks out the file by specifying a version. If the version doesn’t exist, Failed. Otherwise check out the specified version.

 


_PROD="/u01/camel/12.0"
_DEBUG="on"
_LOG="_srcs.log"

fname_srcs="$_PROD/$2"
fname=$(basename "${fname_srcs}")
fdir=`echo "${fname_srcs}" | sed 's/'"$fname"'$//'`
fver="$fdir/RCS/${fname},v"

function DEBUG()
{
	[ "$_DEBUG" == "on" ] && $@ || :
}

if [ $1 == "co" ]; then
	echo "Checkout $2 $3 from SRCS..." | tee -a $_LOG
	if [ ! -f "$fver" ]; then
		echo "$fname doesn't exist in SRCS. Run init and ci command to version control it firstly...<FAILED>" | tee -a $_LOG
		exit 1
	else
		if egrep -v "^\s*$" $fver | wc -l | egrep "^0" > /dev/null ; then
			echo "$fname is just initialled in SRCS. Run ci command to version control it firstly...<FAILED>" | tee -a $_LOG
		elif ! cat $fver | egrep "^version#$3" > /dev/null ; then
			echo "Version $3 doesn't exist...<FAILED>" | tee -a $_LOG
			exit 1
		elif [ "$#" -lt 3 ]; then
			cp $fname_srcs $fname
			echo "Checkout $2 $3 from SRCS...<SUCCESSED>" | tee -a $_LOG
		else
			version=`tail -3 $fver | egrep "^version#" | sed 's/^version#//'`
			cp $fname_srcs $fname
			for (( v=$version; v>$3; v-- ))
			do
				let delta=$v-1
				_l1=`nl "$fver" | egrep "version#$delta" | sed "s/version#$delta//" | sed 's/^\s*|\s*$//g'`
				_l2=`nl "$fver" | egrep "version#$v" | sed "s/version#$v//" | sed 's/^\s*|\s*$//g'`
				sed -n "${_l1},${_l2}p" "$fver" | patch $fname -i - >> /dev/null
			done
			echo "Checkout $2 $3 from SRCS...<SUCCESSED>" | tee -a $_LOG
		fi
	fi
fi

Test data:

Below data is recorded by check in script posted in http://luohuahuang.com/2014/05/17/srcs-startup/ in the filename,v file. It basically records all of the diff changes.
####################################################################

### This is test1.sql file
### I am Version 1
### This line should be the same
###

comment: initial checkin for test1.sql

####################################################################

### This is test1.sql file
### I am Version 2
### This line should be the same
this line is new in version 2
###

comment: hello version 2

####################################################################

### This is test1.sql file
I am Version 3
### This line should be the different
this line is new in version 3
###

comment: okie, version 3

####################################################################

### This is test1.sql file
I am Version 4
hello version4
this line is new in version 4
###

comment: i am version 4.

####################################################################

### This is test1.sql file
I am Version 5
hello version5
haxialg xn
this line is new in version 5
###

comment: hello hello version 5

####################################################################

### This is test1.sql file
I am Version 6
ahoghgoh
gegoruaon
hello version6
haxialg xn
this line is new in version 6
###

version 6 here…

Test Result:

-bash-3.2$ sh srcs.sh co admin/sql/test1.sql 4
Checkout admin/sql/test1.sql 4 from SRCS…
Checkout admin/sql/test1.sql 4 from SRCS…<SUCCESSED>
-bash-3.2$ cat test1.sql
### This is test1.sql file
I am Version 4
hello version4
this line is new in version 4
###
-bash-3.2$ rm test1.sql
-bash-3.2$ sh srcs.sh co admin/sql/test1.sql 2
Checkout admin/sql/test1.sql 2 from SRCS…
Checkout admin/sql/test1.sql 2 from SRCS…<SUCCESSED>
-bash-3.2$ cat test1.sql
### This is test1.sql file
### I am Version 2
### This line should be the same
this line is new in version 2
###
-bash-3.2$ sh srcs.sh co admin/sql/test1.sql 1
Checkout admin/sql/test1.sql 1 from SRCS…
Checkout admin/sql/test1.sql 1 from SRCS…<SUCCESSED>
-bash-3.2$ cat test1.sql
### This is test1.sql file
### I am Version 1
### This line should be the same
###
-bash-3.2$ sh srcs.sh co admin/sql/test1.sql 0
Checkout admin/sql/test1.sql 0 from SRCS…
Version 0 doesn’t exist…<FAILED>

From the test result, the check out script is working!

So far, the scripts can simulate below version control functions:
1. initial a file in the version repository.
2. check in a file into the repository and the repository records the changes.
3. check out a file by specifying a version.
4. It is only for text-based files.

 

Todo list:

1. Lock and unlock
2. Access control
3. branching
4. .etc

I should complete this in later posts.

SRCS – Check in file

Today I got some spare time so I tried to simulate a basic Source Versions Control Tool by using linux patch command. Basically my target is, the tool could be able to handle version control on a standalone env. for a single user, like check in a file, check out a file, check out a file with dedicated version, lock and unlock, log review, etc. Of course, multi-users and CS mode will be supported in future.

This afternoon I just tried to figure out how patch command work. Basically,

Let’s see an example of patch command,

-bash-3.2$ cat file1
This is file 1
I am a file 1
-bash-3.2$ cat file2
This is file 1
This is file 2
I am a file  2
-bash-3.2$ diff file1 file2 > diff.txt
-bash-3.2$ cat diff.txt
2c2,3
< I am a file 1
---
> This is file 2
> I am a file  2
-bash-3.2$ rm file2
-bash-3.2$ cp file1 file2
-bash-3.2$ patch file2 < diff.txt
patching file file2
-bash-3.2$ cat file2
This is file 1
This is file 2
I am a file  2
-bash-3.2$

Currently I just composed an experimental script. The script can do below thing:
1. for a new file, run ‘srcs init file’ to initial a placeholder in the repository.
2. check in a new file and note down the diff in the RCS/file,v file.

For example, for new file admin/sql/test/1.sql, I run ‘srcs init admin/sql/test/1.sql’ it will help me create a control file under $_PROD/admin/sql/test/RCS/1.sql,v.


_PROD="/u01/camel/12.0"
_DEBUG="on"
_LOG="_srcs.log"

fname_srcs="$_PROD/$2"
fname=$(basename "${fname_srcs}")
fdir=`echo "${fname_srcs}" | sed 's/'"$fname"'$//'`
fver="$fdir/RCS/${fname},v"

function DEBUG()
{
	[ "$_DEBUG" == "on" ] && $@ || :
}

if [ $1 == "init" ]; then
	date | tee -a $_LOG
	echo "Initial $2 in SRCS..." | tee -a $_LOG
	mkdir -p "$fdir/RCS"
	if [ -f "$fver" ]; then
		echo "$2 exists in SRCS already...<FAILED>" | tee -a $_LOG
		echo "Initial $2 in SRCS...<FAILED>" | tee -a $_LOG
		exit 1
	fi
	touch "$fver"
	if [ $? -gt 0 ];then
		echo "Initial $2 in SRCS...<FAILED>" | tee -a $_LOG
		exit 1
	fi
	echo "Initial $2 in SRCS...<SUCCESSED>" | tee -a $_LOG
	exit 0
fi

if [ $1 == "ci" ]; then
	echo "Checkin $2 in SRCS..." | tee -a $_LOG
	if [ ! -f "$fname" ]; then
		echo "$fname doesn't exist in local directory...<FAILED>" | tee -a $_LOG
		exit 1
	elif [ ! -f "$fver" ]; then
		echo "$fname doesn't exist in SRCS. Run init command to init it firstly...<FAILED>" | tee -a $_LOG
		exit 1
	else
		if egrep -v "^\s*$" $fver | wc -l | egrep "^0" > /dev/null ; then
			version=1
		else
			version=`tail -3 $fver | egrep "^version#" | sed 's/^version#//'`
			let version=1+$version
		fi
			echo "Input comment for this checkin: "
			read comment
			touch "${fname_srcs}"
			diff $fname $fname_srcs >> $fver
			echo "comment#$comment" >> $fver
			echo "version#$version" >> $fver
			cp $fname $fname_srcs
			echo "Checkin $2 in SRCS...<SUCCESSED>" | tee -a $_LOG
	fi
fi

Output:

-bash-3.2$ srcs.sh ci admin/sql/test1/2.sql
Chekcin admin/sql/test1/2.sql in SRCS...
2.sql doesn't exist in SRCS. Run init command to init it firstly...<FAILED>
-bash-3.2$ srcs.sh init admin/sql/test1/2.sql
Sat May 17 01:17:40 PDT 2014
Initial admin/sql/test1/2.sql in SRCS...
Initial admin/sql/test1/2.sql in SRCS...<SUCCESSED>
-bash-3.2$ srcs.sh ci admin/sql/test1/2.sql
Chekcin admin/sql/test1/2.sql in SRCS...
Input comment for this checkin:
this is the 1st checin for 2.sql. Good luck
Chekcin admin/sql/test1/2.sql in SRCS...<SUCCESSED>
-bash-3.2$ cat /u01/camel/12.0/admin/sql/test1/2.sql
hello world
yes correct
select * from table2;
-bash-3.2$ cat /u01/camel/12.0/admin/sql/test1/RCS/2.sql,v
1,3d0
< hello world
< yes correct
< select * from table2;
comment#this is the 1st checin for 2.sql. Good luck
version#1
-bash-3.2$ vi 2.sql
-bash-3.2$ srcs.sh ci admin/sql/test1/2.sql
Chekcin admin/sql/test1/2.sql in SRCS...
Input comment for this checkin:
okie v2 is coming.
Chekcin admin/sql/test1/2.sql in SRCS...<SUCCESSED>
-bash-3.2$ cat /u01/camel/12.0/admin/sql/test1/2.sql
hello world
no wrong
new line in v2
select * from table2;
-bash-3.2$ cat /u01/camel/12.0/admin/sql/test1/RCS/2.sql,v
1,3d0
< hello world
< yes correct
< select * from table2;
comment#this is the 1st checin for 2.sql. Good luck
version#1
2,3c2
< no wrong
< new line in v2
---
> yes correct
comment#okie v2 is coming.
version#2

In the coming days, I will implement check out files with dedicated versions and add access control to it.