Index: /Dev/trunk/Gruntfile.js
===================================================================
--- /Dev/trunk/Gruntfile.js	(revision 473)
+++ /Dev/trunk/Gruntfile.js	(revision 474)
@@ -9,5 +9,6 @@
 
     grunt.registerTask('default', ['compile']);
-    grunt.registerTask('compile', ['jshint:lint-sources'
+    grunt.registerTask('compile', ['svn-ignore:compile'
+                                  ,'jshint:lint-sources'
                                   ,'htmlhint:lint'
                                   ,'coffeelint:lint'
@@ -17,5 +18,5 @@
                                   ,'usebanner:generated-js'
                                   ,'jshint:lint-generated'
-                                  //,'amd-check' // too smart about plugins, r.js can't find them
+                                //,'amd-check' // too smart about plugins, r.js can't find them
                                   ]);
     grunt.registerTask('build', ['clean:build'
@@ -91,4 +92,19 @@
             ]
         },
+        'svn-ignore': {
+            compile: {
+                files: { src: dest(coffeeMap).concat(dest(lessMap)) }
+            }
+        },
+        'svn-ignore-clean': {
+            clean: {
+                files: [{
+                    expand: true,
+                    cwd: srcDir,
+                    src: ['**', '!node_modules/**', '!client/dojo/**', '!client/dijit/**', '!client/dojox/**', '!client/util/**'],
+                    filter: 'isDirectory'
+                }]
+            }
+        },
         usebanner: {
             'generated-css': { options: { position: 'top',
Index: /Dev/trunk/grunt-tasks/svn-ignore.js
===================================================================
--- /Dev/trunk/grunt-tasks/svn-ignore.js	(revision 474)
+++ /Dev/trunk/grunt-tasks/svn-ignore.js	(revision 474)
@@ -0,0 +1,155 @@
+var _ = require('underscore')
+  , path = require('path');
+
+var regexp = "(\n?)### begin grunt-svn-ignore(.|\n)*### end grunt-svn-ignore[^\n]*(\n?)";
+
+module.exports = function(grunt) {
+
+    grunt.registerMultiTask('svn-ignore',
+                            "Makes sure the specified source files are ignored in Subversion.",
+                            function(){
+        var done = this.async();
+
+        var tasks = _.chain(this.filesSrc)
+                     .groupBy(path.dirname)
+                     .map(function(files, dir) {
+                         return _.partial(updateSvnIgnore,
+                                          dir,
+                                          _.chain(files)
+                                           .map(path.basename)
+                                           .sortBy(_.identity)
+                                           .value());
+                     })
+                     .value();
+
+        grunt.util.async.series(tasks,function(error, results){
+            done(error);
+        });
+    });
+
+    grunt.registerMultiTask('svn-ignore-clean',
+                            "Clean generated ignore sections in Subversion.",
+                            function(){
+        var done = this.async();
+
+        var tasks = _.chain(this.filesSrc)
+                     .map(function(file) {
+                         return _.partial(clearSvnIgnore, file);
+                     })
+                     .value();
+
+        grunt.util.async.series(tasks,function(error, results){
+            done(error);
+        });
+    });
+
+    function updateSvnIgnore(dir,files,callback) {
+        if ( !grunt.file.exists(dir) || !grunt.file.isDir(dir) ) {
+            callback(null);
+            return;
+        }
+        grunt.log.writeln("Updating svn:ignore for '"+dir+"'");
+
+        readSvnIgnore(dir, function(error, ignore) {
+            if ( error ) {
+                callback(error);
+                return;
+            }
+
+            ignore = createIgnore(files, ignore);
+
+            writeSvnIgnore(dir, ignore, function(error) {
+                callback(error);
+            });
+            
+        });
+
+    }
+
+    function clearSvnIgnore(dir,callback) {
+        if ( !grunt.file.exists(dir) || !grunt.file.isDir(dir) ) {
+            callback(null);
+            return;
+        }
+        grunt.log.writeln("Cleaning svn:ignore for '"+dir+"'");
+
+        readSvnIgnore(dir, function(error, ignore) {
+            if ( error ) {
+                callback(error);
+                return;
+            }
+
+            ignore = clearIgnore(ignore);
+            if ( /^\s*$/.test(ignore) ) {
+                deleteSvnIgnore(dir, function(error) {
+                    callback(error);
+                });
+            } else {
+                writeSvnIgnore(dir, ignore, function(error) {
+                    callback(error);
+                });
+            }
+        });
+
+    }
+
+    function createIgnore(files, currentIgnore) {
+        // build autoIgnore section
+        var autoIgnore = "### begin grunt-svn-ignore managed ignores\n### edits will be overwritten when grunt svn-ignore is run";
+        _.each(files, function(file){
+            autoIgnore += "\n"+file;
+        });
+        autoIgnore += "\n### end grunt-svn-ignore managed ignores";
+
+        // replace iff exists or append
+        var re = new RegExp(regexp);
+        var newIgnore = currentIgnore || "";
+        if ( re.test(newIgnore) ) {
+            newIgnore = newIgnore.replace(re,"$1"+autoIgnore+"$2");
+        } else {
+            newIgnore += "\n"+autoIgnore;
+        }
+
+        return newIgnore;
+    }
+    
+    function clearIgnore(currentIgnore) {
+        // replace iff exists or append
+        var re = new RegExp(regexp);
+        var newIgnore = currentIgnore || "";
+        newIgnore = newIgnore.replace(re,"");
+        return newIgnore;
+    }
+    
+    function readSvnIgnore(dir,callback) {
+        return svnCommand('svn',
+                          ['propget', 'svn:ignore', dir],
+                          callback);
+    }
+
+    function writeSvnIgnore(dir,ignore,callback) {
+        return svnCommand('svn',
+                          ['propset', 'svn:ignore', ignore, dir],
+                          callback);
+    }
+    
+    function deleteSvnIgnore(dir,callback) {
+        return svnCommand('svn',
+                          ['propdel', 'svn:ignore', dir],
+                          callback);
+    }
+    
+    function svnCommand(cmd,args,callback) {
+        grunt.util.spawn({
+            cmd: cmd,
+            args: (args || [])
+        }, function(error, result, code) {
+            if ( error ) {
+                callback(error);
+                return;
+            }
+            callback(null,result.stdout);
+        });
+    }
+    
+};
