views:

784

answers:

2

In SVN is there any way to set (bugtraq) properties on all directories in a tree without checking out the whole tree?

I can't set properties in the repository directly without setting hooks. Even if I could I'm not sure this would help - you can't set recursive properties with Tortoise, and I suspect it wouldn't be straightforward with the command line client.

There are sparse checkouts - but if I set depth empty for each directory, then setting properties recursively won't work even if I manually check out each subdirectory.

I could check out the whole repository and use Tortoise to set the bugtraq properties on the directories recursively (they don't get applied to files by default). But that's going to require me checking out the entire repository just for this.

Is there a better way to do it that I'm missing?

Edit:

I tried checking out the whole repository and changing the properties at the root - but the commit violated our pre-commit hook: can't change properties on tags. Without removing the hook, it looks like I'm going to need to manually change the properties (on everything apart from tags).

+1  A: 

Getting a list of all the directories might be a good first step. Here's one way to do that without actually checking anything out:

  1. Create a text file with the contents of the repository:

    svn list --depth infinity https://myrepository.com/svn/path/to/root/directory > everything.txt

  2. Trim it down to just the directories. Directories will all end with a forward slash:

    grep "/$" everything.txt > just_directories.txt

In your case you'll want to open it up in a text editor and take out the tag directories your hooks choke on.

Since you've got the repository checked out you can use that file directly as input to a propset operation:

svn propset myprop myvalue --targets just_directories.txt

I wanted to set the properties directly on the repository versions of the files without checking them out first, but it didn't work. I prepended each directory name with the repository path (https://myrepository.com/svn/path/to/root/directory) and tried *svn propset myprop mypropvalue --targets just_directories.txt* but it gave an error: svn: Setting property on non-local target 'https://myrepository.com/svn/path/to/root/directory/subdir1' needs a base revision. Not sure if there's a way around that.

Darryl
The "needs a base revision" message is because you can't set versioned properties on repositories, only on working copies.
Simon D
Looks like the original poster couldn't do what he wanted without checking out the full tree.Incidentally, tortoise lets you set properties on a directory in the repository, without checking it out, through their repository browser. You can only do one directory at a time though.
Darryl
+1  A: 

I ended up writing a script to do this using the pysvn bindings (which are very easy to use). It's below in case anybody wants it.

import sys
import os
from optparse import OptionParser
import pysvn
import re

usage = """%prog [path] property-name property-value

Set property-name to property-value on all non-tag subdirectories in an svn working copy.

path is an optional argument and defaults to "."
"""

class Usage(Exception):
    def __init__(self, msg):
        self.msg = msg

def main():
    try:
        parser = OptionParser(usage)
        (options, args) = parser.parse_args()

        if len(args) < 2:
            raise Usage("Must specify property-name and property-value")
        elif len(args) == 2:
            directory = "."
            property_name = args[0]
            property_value = args[1]
        elif len(args) == 3:
            directory = args[0]
            property_name = args[1]
            property_value = args[2]
        elif len(args) > 3:
            raise Usage("Too many arguments specified")

        print "Setting property %s to %s for non-tag subdirectories of %s" % (property_name, property_value, directory)

        client = pysvn.Client()
        for path_info in client.info2(directory):
            path = path_info[0]
            if path_info[1]["kind"] != pysvn.node_kind.dir:
                #print "Ignoring file directory: %s" % path
                continue
            remote_path = path_info[1]["URL"]
            if not re.search('(?i)(\/tags$)|(\/tags\/)', remote_path):
                print "%s" % path
                client.propset(property_name, property_value, path, depth=pysvn.depth.empty)
            else:
                print "Ignoring tag directory: %s" % path
    except Usage, err:
        parser.error(err.msg)
        return 2


if __name__ == "__main__":
    sys.exit(main())
Simon D