CVS diff with new files: fakeadd

Ever been disgruntled by the fact that you can't do a cvs diff with new files, because you haven't got write access on a Drupal contrib module's CVS repository and thus can't cvs add those new files? There's a solution though: edit CVS's Entries file. But who likes manually modifying files over and over again?

The solution: fakeadd! (I've attached the file to this post in case this site ever goes down.) This nice shellscript allows you to update the Entries file using a simple syntax: fakeadd  newfile.php.

A quick install how-to:

  1. Save the file to a location of your choice, I've saved it in ~/scripts.
  2. Open your ~/.bash_profile file (if you're using the bash shell, this is the default shell on OS X) and add the following:
    1. # Add custom scripts, such as the CVS fakeadd script.
    2. export PATH=$PATH:~/scripts
  3. Make the script executable: chmod +x ~/scripts/fakeadd.
  4. When you create patches (also see this blog post of mine), use the -N flag. So your eventual command will look like this: cvs diff -N -up > foo.patch.

Updated on November 30, 2008. The above blog post was improved based on the feedback I got in the comments:

  • Robert Douglass mentioned in the comments that you have to pass the -N parameter for cvs diff to pick up new files.
  • drewish was kind enough to post an improved version in the comments, which allows you to use the script for files in subdirectories.

AttachmentSize
fakeadd770 bytes
Tags

Comments

It works. A couple extra pointers...

First, run the fakeadd script from the directory where the new file lives. If you're adding some new unit tests to D7, for example, they might be in ./includes/tests. fakeadd changes the CVS/Entries file in the current directory, so to add ./includes/tests/foo.test, you need to cd to includes/tests first.

Second, when making the patch, you need the -N flag:
cvs diff -N -up > foo.patch

Very handy!

Thanks very much for this script! Had troubles patching with a new file and this worked perfectly!

humm....

i was trying to use this as "fakeadd modules/*/*.api.php" and it failed miserably. i'm trying to decide if it'd be worth hacking it to get this to work correctly or if i should just add them by hand...

there fixed that for you ;)

#!/bin/sh

if [ $# -eq 0 ]; then
	echo "usage: $0 file ..." 1>&2
	exit 1
fi

rv=0
for file in "$@"; do
	dir=`dirname $file`
	base=`basename $file`
	if [ -f "$file" ]; then :; else
		echo "$0: error: \"$file\" does not exist or is not a plain file"
		rv=1
		continue
	fi
	if [ -d "$dir/CVS" ]; then :; else
		echo "$0: fatal error: no CVS directory!
		rv=1
		continue
	fi
	if [ -f "$dir/CVS/Entries" ] && [ -w "$dir/CVS/Entries" ]; then :; else
		echo "$0: fatal error: CVS/Entries file not writable!
		rv=1
		continue
	fi

	if grep "^/$file/" "$dir/CVS/Entries" > /dev/null 2>&1; then
		echo "$0: error: \"$file\" is already listed in CVS/Entries"
		rv=1
		continue
	fi

	echo "/$base/0/dummy timestamp//" >> "$dir/CVS/Entries"
	echo "$0: added \"$file\""
done
exit $rv

Thanks, I updated the blog

Thanks, I updated the blog post!

Alternative approach: cvsdo

Just thought I'd throw out there that I stumbled across this post (and it didn't /quite/ work for me, though I appreciated that other Drupalers were attempting to solve this) slightly before this one.

Down in the section titled "Including new files in a patch", it mentions a nice utility called cvsdo (source is here, but see below if you're a Debianite), which accomplished this task quite nicely, and comes with other useful cvs utilities such as cvschroot which lets you change the Root entry (recursively!) for a working copy (ie. from an anonymous checkout to a logged-in one, for instance).

Even better was the fact that, on my debian-based system, all I had to do was apt-get install cvsutils and kapow! I had 'cvsdo' at my service :)

Thanks, great tip!

Thanks, great tip!

Added to drupal.org

Added to drupal.org documentation page. both this script and cvsdo, cvsutils.
http://drupal.org/node/323

Cheers
Frank Carey

Pingback

[...] command fails without write access to the repository. Luckely there is a handy little tool called fakeadd which you can use to edit the CVS entries file and let it look like the new files have been [...]

This is awesome!

You should get this into the official patch docs. The current setup is really a pain for a big patches with multiple dirs.

Syntax errors

I notice there are some missing trailing quotes (") on two of the echo statements.
That will make echo print "what you want ... plus every thing up to next echo with leading"

Here's a patch that fixes it (plus I added a line with a URL back here :).

--- /tmp/1/fakeadd      2010-01-08 10:49:37.051730790 -0600
+++ /tmp/2/fakeadd      2010-01-08 10:49:13.531058172 -0600
@@ -1,4 +1,5 @@
#!/bin/sh
+# from http:/wimleers.com/blog/cvs-diff-new-files-fakeadd

if [ $# -eq 0 ]; then
        echo "usage: $0 file ..." 1>&2
@@ -15,12 +16,12 @@ for file in "$@"; do
                continue
        fi
        if [ -d "$dir/CVS" ]; then :; else
-               echo "$0: fatal error: no CVS directory!
+               echo "$0: fatal error: no CVS directory!"
                rv=1
                continue
        fi
        if [ -f "$dir/CVS/Entries" ] && [ -w "$dir/CVS/Entries" ]; then :; else
-               echo "$0: fatal error: CVS/Entries file not writable!
+               echo "$0: fatal error: CVS/Entries file not writable!"
                rv=1
                continue
        fi

Nice post. Love your work

Nice post. Love your work hope to see some more cool stuff soon.

Upgrade your VCS

I'm surprised nobody has mentioned it yet. Just use bzr or git and you won't have these problems. There are well maintained bzr and git mirrors of Drupal. See detailed instructions for git at http://drupal.org/node/707484

It doesn't help getting your

It doesn't help getting your code into drupal.org's CVS though. It's possible, but that kind of set up is quite hard IIRC.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <h2> <h3> <h4> <h5> <h6> <pre> <s>
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.
  • Lines and paragraphs break automatically.
  • Insert Flickr images: [flickr-photo:id=230452326,size=s] or [flickr-photoset:id=72157594262419167,size=m].
Syndicate content