You can subscribe to this list here.
2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(47) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2003 |
Jan
(140) |
Feb
(98) |
Mar
(152) |
Apr
(104) |
May
(71) |
Jun
(94) |
Jul
(169) |
Aug
(83) |
Sep
(47) |
Oct
(134) |
Nov
(7) |
Dec
(20) |
2004 |
Jan
(41) |
Feb
(14) |
Mar
(42) |
Apr
(47) |
May
(68) |
Jun
(143) |
Jul
(65) |
Aug
(29) |
Sep
(40) |
Oct
(34) |
Nov
(33) |
Dec
(97) |
2005 |
Jan
(29) |
Feb
(30) |
Mar
(9) |
Apr
(37) |
May
(13) |
Jun
(31) |
Jul
(22) |
Aug
(23) |
Sep
|
Oct
(37) |
Nov
(34) |
Dec
(117) |
2006 |
Jan
(48) |
Feb
(6) |
Mar
(2) |
Apr
(71) |
May
(10) |
Jun
(16) |
Jul
(7) |
Aug
(1) |
Sep
(14) |
Oct
(17) |
Nov
(25) |
Dec
(26) |
2007 |
Jan
(8) |
Feb
(2) |
Mar
(7) |
Apr
(26) |
May
|
Jun
(12) |
Jul
(30) |
Aug
(14) |
Sep
(9) |
Oct
(4) |
Nov
(7) |
Dec
(6) |
2008 |
Jan
(10) |
Feb
(10) |
Mar
(6) |
Apr
(8) |
May
|
Jun
(10) |
Jul
(18) |
Aug
(15) |
Sep
(16) |
Oct
(5) |
Nov
(3) |
Dec
(10) |
2009 |
Jan
(11) |
Feb
(2) |
Mar
|
Apr
(15) |
May
(31) |
Jun
(18) |
Jul
(11) |
Aug
(26) |
Sep
(52) |
Oct
(17) |
Nov
(4) |
Dec
|
2010 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <sv...@ww...> - 2004-06-06 08:18:44
|
Author: mkrose Date: 2004-06-06 01:18:37 -0700 (Sun, 06 Jun 2004) New Revision: 998 Modified: trunk/CSP/tools/sublib.py trunk/CSP/tools/subset Log: Subset diff enhancements: o Allow diff revisions to be specified. o Accept multiple diff paths. o Check svn diff return code and disable links for diffs that fail. Modified: trunk/CSP/tools/sublib.py =================================================================== --- trunk/CSP/tools/sublib.py 2004-06-06 07:31:09 UTC (rev 997) +++ trunk/CSP/tools/sublib.py 2004-06-06 08:18:37 UTC (rev 998) @@ -106,9 +106,13 @@ return os.path.abspath(os.path.dirname(svn_rootsvn())) -def svn_savediff(file, target, context=100): +def svn_savediff(file, target, revision=None, context=100): path = file.path - exit_code, out = runo('svn diff --diff-cmd diff -x "-U %d" %s' % (context, path)) + if revision: + revision = '-r %s' % revision + else: + revision = '' + exit_code, out = runo('svn diff %s --diff-cmd diff -x "-U %d" %s' % (revision, context, path)) open(target, 'w').write(''.join(out)) return exit_code Modified: trunk/CSP/tools/subset =================================================================== --- trunk/CSP/tools/subset 2004-06-06 07:31:09 UTC (rev 997) +++ trunk/CSP/tools/subset 2004-06-06 08:18:37 UTC (rev 998) @@ -358,20 +358,33 @@ self.save() return Result(0) - def diff(self, name): + def diff(self, names, revision): dircmd = os.environ.get('SUBSET_DIFF_DIR', '') onecmd = os.environ.get('SUBSET_DIFF_ONE', dircmd) cs = None - if not name: + if not names: + name = 'default changeset' files = filter(self._closed, sublib.svn_st()) - elif os.path.exists(name): + elif len(names) > 1 or os.path.exists(names[0]): files = sublib.svn_st() - path = os.path.abspath(name) - files = [x for x in files if x.abspath() == path] - if not files: - print '%s unmanaged or unchanged' % name + diffs = [] + for file in files: + path = file.abspath() + for name in names: + name = os.path.abspath(name) + if os.path.isdir(name): + if path.startswith(name): + diffs.append(file) + break + else: + if name == path: + diffs.append(file) + break + if not diffs: return Result(0) + files = diffs else: + name = names[0] cs = self.getChangeset(name) if not cs: return Error('no changeset "%s"' % name) @@ -405,14 +418,19 @@ else: index.write('<h3>%s</h3>' % name) cleanup.append(diffindex) + if revision: + index.write('<b>diff to revision %s</b>' % revision) index.write('<ul>\n') for file in files: outbase = file.path.replace(os.path.sep, '~') + '.diff' outfile = os.path.join(tmproot, outbase) cleanup.append(outfile) - sublib.svn_savediff(file, outfile) + exit_code = sublib.svn_savediff(file, outfile, revision) if makeindex: - index.write('<li><a href="%s">%s</a></li>\n' % (outbase, file.path)) + if exit_code: + index.write('<li>%s <i>...unable to diff</i></li>\n' % (file.path)) + else: + index.write('<li><a href="%s">%s</a></li>\n' % (outbase, file.path)) if makeindex: index.write('</ul>\n</small></body></html>') index.close() @@ -859,22 +877,16 @@ def _define(self): self._long = ('diff: generate diffs for files or changesets.\n' '\n' - 'usage: %prog diff [changeset|file]' + 'usage: %prog diff [changeset | file [file...]]' '\n' 'If no arguments are specified, all files in the default changeset\n' 'will be diffed') self._short = 'generate diffs' self._addKeys('diff') + self._addOption('-r', '--revision', default='', metavar='REV', help='diff relative to a specific revision') def _run(self, options, args): - if len(args) > 1: - self.help() - return 1 - if len(args) == 0: - name = '' - else: - name = args[0] - return run('diff', name) + return run('diff', args, options.revision) class Help(Command): @@ -885,7 +897,6 @@ 'usage: %prog help [SUBCOMMAND...]') self._short = 'describe subcommands' self._addKeys('help', 'h', '?') - self._addOption('-r') def _run(self, options, args): if len(args) == 1: |
From: <sv...@ww...> - 2004-06-06 07:31:17
|
Author: mkrose Date: 2004-06-06 00:31:09 -0700 (Sun, 06 Jun 2004) New Revision: 997 Modified: trunk/CSP/tools/subset Log: Add some pass-through svn commands. Modified: trunk/CSP/tools/subset =================================================================== --- trunk/CSP/tools/subset 2004-06-06 06:17:45 UTC (rev 996) +++ trunk/CSP/tools/subset 2004-06-06 07:31:09 UTC (rev 997) @@ -33,9 +33,8 @@ # TODO # clean up error reporting of review submit # diffstats -# work with tkdiff by piping through undiff +# complete svn wrapping - import sys import os import os.path @@ -618,7 +617,8 @@ self._options.append((args, kw)) def _makeOpt(self): - opt = optparse.OptionParser(usage=self._long, + usage = '%s\n' % self._long + opt = optparse.OptionParser(usage=usage, add_help_option=0, formatter=app.CustomUsageFormatter()) for optargs, optkw in self._options: @@ -640,10 +640,58 @@ run = staticmethod(run) +class SVNCommand(Command): + + def _start(self, args): + command = self._keys[0] + os.execvp('svn', ['svn', command] + args) + + def help(self): + command = self._keys[0] + os.execvp('svn', ['svn', 'help', command]) + + +class Blame(SVNCommand): + def _define(self): + self._addKeys('blame', 'praise', 'annotate', 'ann') + self._short = 'show revision and author for each line in a file' + + +class Log(SVNCommand): + def _define(self): + self._addKeys('log') + self._short = 'show log messages for revisions and/or files' + + +class Info(SVNCommand): + def _define(self): + self._addKeys('info') + self._short = 'display information about a path' + + +class List(SVNCommand): + def _define(self): + self._addKeys('list', 'ls') + self._short = 'list diretory entries in the repository' + + +class Status(SVNCommand): + def _define(self): + self._addKeys('status', 'stat', 's') + self._short = 'show the status of working copy files and directories' + + +class Cat(SVNCommand): + def _define(self): + self._addKeys('cat', 'print') + self._short = 'output the content of specified files or URLs' + + class Opened(Command): def _define(self): - self._long = ('opened (o): Show open files.\n' + self._long = ('opened (o): list files that have been modified, added, or deleted.\n' + '\n' 'usage: %prog opened [path]') self._short = 'show opened files' self._addKeys('opened', 'o') @@ -656,7 +704,8 @@ class Changes(Command): def _define(self): - self._long = ('changes: Show all active changesets.\n' + self._long = ('changes: list all active changesets.\n' + '\n' 'usage: %prog changes [options]') self._short = 'show active changesets' self._addKeys('changes') @@ -671,9 +720,11 @@ def _define(self): self._long = ('assign (a): assign files to an existing changeset, or move files\n' - ' from one changeset to another\n' + 'from one changeset to another\n' + '\n' 'usage: %prog assign changeset file [file...]\n' - 'If changeset is "default", the files will be removed from all changesets.') + '\n' + 'If changeset is "default", the files will be removed from named changesets.') self._short = 'reassign open files to a different changeset' self._addKeys('assign', 'a') @@ -690,6 +741,7 @@ def _define(self): self._long = ('change: create or edit a changeset\n' + '\n' 'usage: %prog change [options] changeset') self._short = 'create or edit a changeset' self._addKeys('change') @@ -710,6 +762,7 @@ def _define(self): self._long = ('review: distribute a changeset for review\n' + '\n' 'usage: %prog review [options] changeset\n' '\n' 'Creates a zipfile containing diffs of all files in the changeset.\n' @@ -753,6 +806,7 @@ def _define(self): self._long = ('submit: submit (commit) a changeset to the repository\n' + '\n' 'usage: %prog submit changeset') self._short = 'submit a changeset to the repository' self._addKeys('submit') @@ -768,8 +822,9 @@ class Abandon(Command): def _define(self): - self._long = ('abandon: discard an existing changeset. open files will be reassigned\n' + self._long = ('abandon: discard a named changeset. files in that changeset will be reassigned\n' 'to the default changeset.\n' + '\n' 'usage: %prog abandon changeset') self._short = 'abandon a changeset' self._addKeys('abandon') @@ -786,6 +841,7 @@ def _define(self): self._long = ('describe (d): show information about a changeset.\n' + '\n' 'usage: %prog describe changeset') self._short = 'describe a changeset' self._addKeys('describe', 'd') @@ -802,7 +858,11 @@ def _define(self): self._long = ('diff: generate diffs for files or changesets.\n' - 'usage: %prog diff [changeset|file]') + '\n' + 'usage: %prog diff [changeset|file]' + '\n' + 'If no arguments are specified, all files in the default changeset\n' + 'will be diffed') self._short = 'generate diffs' self._addKeys('diff') @@ -821,6 +881,7 @@ def _define(self): self._long = ('help (?, h): Describe the usage of this program or its subcommands.\n' + '\n' 'usage: %prog help [SUBCOMMAND...]') self._short = 'describe subcommands' self._addKeys('help', 'h', '?') @@ -849,12 +910,8 @@ primaries.sort() for primary in primaries: command = commands[primary] - aliases = command._keys[1:] - aliases = ', '.join(aliases) subcommand = primary - if aliases: - subcommand = subcommand + ' (%s)' % aliases - print ' %-20s %s' % (subcommand, command._short) + print ' %-14s %s' % (subcommand, command._short) print @@ -870,7 +927,15 @@ Review() Submit() +# svn subcommands +Blame() +Cat() +Info() +List() +Log() +Status() + def main(args): if len(args) < 1: app.usage() |
From: <sv...@ww...> - 2004-06-06 06:17:55
|
Author: mkrose Date: 2004-06-05 23:17:45 -0700 (Sat, 05 Jun 2004) New Revision: 996 Removed: trunk/CSP/tools/pyrun.stub Modified: trunk/CSP/tools/pyrun Log: Add docstring to pyrun, internalize the stub, and cleanup the zipfile construction by eliminating duplicate modules. Also be more careful to include all necessary __init__.py modules. Modified: trunk/CSP/tools/pyrun =================================================================== --- trunk/CSP/tools/pyrun 2004-06-06 01:46:40 UTC (rev 995) +++ trunk/CSP/tools/pyrun 2004-06-06 06:17:45 UTC (rev 996) @@ -40,9 +40,17 @@ import bootstrap from CSP.base import app -DEFAULT_STUB = 'pyrun.stub' +DEFAULT_STUB = ("python2.3 -c \"" + "import sys;" + "sys.path.insert(0, '$0');" + "sys.argv[0]='$0';" + "import %s" + "\" ${1+\"$@\"};" + "exit $?") +PROGRAM_MODULE = '__main__' + def main(args): if len(args) != 1: app.usage() @@ -57,6 +65,10 @@ def findCustomModules(modules): + """ + Filter a list of modules, returning only those that are not part of the + standard python libraries. + """ re_stdlib = re.compile(r'[/\\][pP]ython[\.0-9]*[/\\]') custom = [] for mod in modules: @@ -73,12 +85,21 @@ def findDependencies(program, path): + """ + Use the python modulefinder to find all modules that the main program + imports (directly and indirectly). We then filter out the ones that + are part of the standard python library. + """ mf = ModuleFinder(path) mf.run_script(program) custom = findCustomModules(mf.modules.values()) names = [x.__name__ for x in custom] missing = {} ignore = app.options.ignore + # ModuleFinder generally reports some modules as missing. It seems + # sufficient to ignore any that aren't directly imported by any of + # the custom modules. Others false alarms (such as os.path) can be + # explicitly ignored via command-line flags. for name, calldict in mf.badmodules.items(): for caller in calldict.keys(): if caller in names: @@ -94,56 +115,108 @@ def makeZip(zipname, program, modules, path): + """ + Assemble the custom modules into a zip archive. We try to construct the + archive to mirror the path hierarchy of the custom modules. + """ + # PyZipFile automatically precompiles python sources. out = zipfile.PyZipFile(zipname, 'w', compression=zipfile.ZIP_DEFLATED) + main_module = '' + uniq_modules = {} + # modules may appear multiple times, depending on the use of relative + # import statements, but the absolute filenames are unique. for module in modules: name = module.__name__ file = module.__file__ + if uniq.has_key(file): continue + # determine the full module path relative to sys.path basename = '' + # loop through all the paths in sys.path, finding the first one that + # can be used to import the module. in principle, we really should + # check that all intermediate directories (see basename below) are + # actually packages. for p in path: if file.startswith(p): + # this module can be imported using 'from basename import name' basename = os.path.dirname(file)[len(p):] + if os.path.isabs(basename): basename = basename[1:] break - if os.path.isabs(basename): - basename = basename[1:] + if basename: + # now look at all the intermediate directories (which we assume + # are packages) and add the '__init__.py' modules by hand. this + # is necessary because modulefinder won't always notice them. + search = basename + while search: + package_dir = os.path.join(p, search) + init = os.path.join(package_dir, '__init__.py') + if os.path.exists(init): + uniq_modules[init] = ('__init__', search) + else: + # if our assumption fails, at least warn the user. if this + # happens at all frequently, the package search should be + # moved inside the path search loop. + print 'WARNING: expected %s to be a package, but' % package_dir + print ' __init__.py does not exist.' + # walk up the package hierarchy + search = os.path.dirname(search) + uniq_modules[file] = (name, basename) + + # now add all unique modules to the zip archive + for file in uniq_modules.keys(): + name, basename = uniq_modules[file] + # special case for the main program module if file == program: - f = open('pyx_program.py', 'w') + program_filename = PROGRAM_MODULE + '.py' + f = open(program_filename, 'w') # big ol' hack. insert some magic to make the main script look like it - # was run directly instead of imported. better solutions welcome... + # was run directly instead of imported. better solutions welcome. note + # than setting __name__ to '__main__' is not always sufficient (e.g. + # pickle can complain about missing classes when loading). inject = 1 for line in open(program): - if (inject and (line.startswith('import') or line.startswith('app.start(') or - line.startswith('if __name__ =='))): + if (inject and (line.startswith('app.start(') or line.startswith('if __name__ =='))): inject = 0 print >>f, "import sys; sys.modules['__main__'] = sys.modules[__name__]; __name__ = '__main__';" print >>f, line, f.close() - out.writepy('pyx_program.py') + out.writepy(program_filename, basename) + main_module = '.'.join(basename.split(os.sep) + [PROGRAM_MODULE]) for ext in ('.py', '.pyc', '.pyo'): - pyx_name = 'pyx_program' + ext - if os.path.exists(pyx_name): os.unlink(pyx_name) + prog_name = PROGRAM_MODULE + ext + if os.path.exists(prog_name): os.unlink(prog_name) elif file.endswith('.py'): out.writepy(file, basename) - if os.path.dirname(file) == os.path.dirname(program): - out.writepy(file) else: + # in principle anything can be added to the archive, but we don't + # actively support arbitrary data and shared libaries yet. + print 'WARNING: adding non-python file %s' % file out.write(file, os.path.basename(file)) if not app.options.quiet: print '.. Added %s (%s)' % (name, file) out.close() + assert main_module + return main_module -def addStub(stub, tmpname, target): +def addStub(stub, main_module, tmpname, target): + """ + Add a stub to the start of the zipfile to bootstrap the main program. + The stub puts the zipfile at the start of sys.path, and tweaks sys.argv + before importing the main module. + """ zip = open(tmpname, 'r') - stub = open(stub, 'r') out = open(target, 'w') - out.write(stub.read()) + out.write((stub % main_module) + '\n') out.write(zip.read()) - stub.close() zip.close() out.close() def getPath(program): + """ + Get sys.path as seen by the application program, including any paths + specified by --addpath flags. + """ path = sys.path[:] path[0] = os.path.dirname(program) addpaths = app.options.addpath[:] @@ -154,12 +227,20 @@ def assemble(program, target): + """ + Find all module dependencies, construct the zip archive, and prepend the + bootstrap stub. + """ path = getPath(program) stub = app.options.stub - if not os.path.exists(stub): - print 'Stub file %s not found, aborting' % stub - sys.exit(1) + if stub: + if not os.path.exists(stub): + print 'Stub file %s not found, aborting' % stub + sys.exit(1) + stub = open(stub).read() + else: + stub = DEFAULT_STUB if os.path.exists(target) and not app.options.force: print '%s already exists, aborting' % target @@ -174,8 +255,8 @@ print 'Creating executable %s' % target tmpname = target + "~" - makeZip(tmpname, program, modules, path) - addStub(stub, tmpname, target) + main_module = makeZip(tmpname, program, modules, path) + addStub(stub, main_module, tmpname, target) os.unlink(tmpname) os.chmod(target, 0755) @@ -184,11 +265,12 @@ print 'Done.' +# command line options app.addOption('--addpath', metavar='PATH', action='append', default=[], help='add path to sys.path') app.addOption('-q', '--quiet', action='store_true', default=False, help='quiet mode (less verbose)') app.addOption('--output', metavar='FILE', default=None, help='specify output file') app.addOption('-f', '--force', action='store_true', default=False, help='overwrite existing output file') -app.addOption('--stub', metavar='STUBFILE', default=DEFAULT_STUB, help='stub file to use') +app.addOption('--stub', metavar='STUBFILE', default='', help='stub file to use') app.addOption('--ignore', metavar='MODULE', action='append', default=['os.path'], help='ignore unresolved module dependency') app.start() Deleted: trunk/CSP/tools/pyrun.stub =================================================================== --- trunk/CSP/tools/pyrun.stub 2004-06-06 01:46:40 UTC (rev 995) +++ trunk/CSP/tools/pyrun.stub 2004-06-06 06:17:45 UTC (rev 996) @@ -1 +0,0 @@ -python2.3 -c "import sys; sys.path[0]='$0'; sys.argv[0]='$0'; import pyx_program" ${1+"$@"}; exit $? |
From: <sv...@ww...> - 2004-06-06 01:46:47
|
Author: mkrose Date: 2004-06-05 18:46:40 -0700 (Sat, 05 Jun 2004) New Revision: 995 Added: trunk/CSP/tools/undiff Modified: trunk/CSP/base/app.py Log: Add a tool for splitting a diff file into two files that resemble the orignal files used to create the diff. Also minor tweaks to app.py: print a blank line after usage, and add a fatal(msg) method that prints to stderr and terminates the program. Modified: trunk/CSP/base/app.py =================================================================== --- trunk/CSP/base/app.py 2004-06-05 23:39:52 UTC (rev 994) +++ trunk/CSP/base/app.py 2004-06-06 01:46:40 UTC (rev 995) @@ -85,7 +85,13 @@ def usage(): """Print usage to stdout.""" opt.print_help() + print +def fatal(msg): + """Print an error message to stderr and terminate with exit code 1.""" + print >>sys.stderr, msg + sys.exit(1) + def programPath(): """Return the absolute path of the application program.""" return os.path.abspath(sys.argv[0]) Added: trunk/CSP/tools/undiff =================================================================== --- trunk/CSP/tools/undiff 2004-06-05 23:39:52 UTC (rev 994) +++ trunk/CSP/tools/undiff 2004-06-06 01:46:40 UTC (rev 995) @@ -0,0 +1,130 @@ +#!/usr/bin/python +# +# Copyright 2004 Mark Rose <mk...@us...> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +""" +%(prog)s: A tool for splitting a unified diffs. + +Takes a unified diff as input and produces two output files that approximate +the files used to create the diff. Regions between diff hunks are padded by +blank lines. Useful for graphical diff tools that require two input files. + +Usage: %(prog)s [options] diff + +The output files are either written to the paths specified by the --output1 +and --output2 flags, or the output filenames will be generated from contents +of the diff and placed in the directory specified by --outdir. In the latter +case, the names of the output files are printed to stdout in the format +"output1 output2". +""" + +import sys +import os + +import bootstrap +from CSP.base import app + + +app.addOption('--output1', metavar='PATH', default='', help='output path for original file') +app.addOption('--output2', metavar='PATH', default='', help='output path for modified file') +app.addOption('--outdir', metavar='DIR', default='', help='output directory') +app.addOption('-f', '--force', action='store_true', default=False, help='overwrite existing output files') + + +def main(args): + if len(args) != 1: + app.usage() + return 1 + diff = args[0] + undiff(diff) + return 0 + + +def output(name): + if app.options.output1 or app.options.output2: + out1 = app.options.output1 + out2 = app.options.output2 + if not out1 or not out2: + app.fatal('Must specify both --output1 and --output2') + if app.options.outdir: + app.fatal('Cannot use the --outdir flag with --output1 and --output2') + else: + path = app.options.outdir + if not path: + app.fatal('Must either specify --outdir, or --output1 and --output2.') + if not os.path.exists(path) or not os.path.isdir(path): + app.fatal('The path specified by --outdir must be a valid directory.') + if not name: name = 'diff' + name = name.replace(os.sep, '~') + out = os.path.join(path, name) + out1 = out + '.1' + out2 = out + '.2' + print '%s %s' % (out1, out2) + if not app.options.force: + for outpath in (out1, out2): + if os.path.exists(outpath): + app.fatal('Output path "%s" exists (use --force to overwrite); aborting.' % outpath) + return open(out1, 'w'), open(out2, 'w') + + +def undiff(diff): + count1 = 0 + count2 = 0 + skip = 2 + for i, line in enumerate(open(diff).readlines()): + if i == 0: + if line.startswith('Index: '): + out1, out2 = output(line.split()[1]) + skip += 1 + continue + else: + out1, out2 = output('') + if i == 1 and line.startswith('================================='): + skip += 1 + continue + if i < skip: + assert line.startswith('--- ') or line.startswith('+++ ') + continue + if line.startswith('@@ '): + parts = line.split() + block1, block2 = parts[1:3] + line1 = int(block1.split(',')[0][1:]) + line2 = int(block2.split(',')[0][1:]) + for n in range(count1, line1): out1.write('\n') + for n in range(count2, line2): out2.write('\n') + count1 = line1 + count2 = line2 + continue + if line.startswith('-'): + out1.write(line[1:]) + count1 += 1 + continue + if line.startswith('+'): + out2.write(line[1:]) + count2 += 1 + continue + out1.write(line[1:]) + count1 += 1 + out2.write(line[1:]) + count2 += 1 + out1.close() + out2.close() + + +app.start() + Property changes on: trunk/CSP/tools/undiff ___________________________________________________________________ Name: svn:executable + * |
From: <sv...@ww...> - 2004-06-05 23:40:01
|
Author: mkrose Date: 2004-06-05 16:39:52 -0700 (Sat, 05 Jun 2004) New Revision: 994 Modified: trunk/CSP/tools/sublib.py trunk/CSP/tools/subset Log: Add a rudimentary diff function to subset. Relies on external tools to actually display the diffs. Under KDE this can be done fairly easily using Konqueror + Kompare. To use this feature, you need to define the SUBSET_DIFF_ONE and/or SUBSET_DIFF_DIR environment variables. The former is run for single diffs (e.g. "subset diff foo/bar.cpp"). Subset generates a unified diff for the specified file, and passes the diff file as an argument to the SUBSET_DIFF_ONE command. Under KDE, you might set this variable to 'kompare'. Some graphical diff viewers (notably tkdiff) can't handle premade diff files. In that case you might can use undiff.py to split the diff into two temporary files. For changes to multiple files (e.g. "svn diff changeset" or just "svn diff"), the various diffs are placed in a temporary directory, along with an index.html file. Subset runs the SUBSET_DIFF_DIR command, passing the temporary directory as an argument. This works nicely with graphical file browsers that understand .diff files. Under KDE, SUBSET_DIFF_DIR='konqueror --profile diff' is a good choice. You should setup your profile to use the index.html file for rendering the directory contents, and customize the default window size. Assuming that everything is installed correctly, clicking on the individual diffs should launch kompare. Modified: trunk/CSP/tools/sublib.py =================================================================== --- trunk/CSP/tools/sublib.py 2004-06-05 20:48:34 UTC (rev 993) +++ trunk/CSP/tools/sublib.py 2004-06-05 23:39:52 UTC (rev 994) @@ -59,6 +59,7 @@ info[line[:idx]] = line[idx+1:].strip() return info + def svn_st(files=None): root = svn_root() if not files: @@ -84,10 +85,12 @@ files.append(File(relpath, root, mode)) return files + #def svn_info(path): # info = os.popen('svn info %s' % path) # app.log.info(info.readlines()) + def svn_rootsvn(): path = '.svn' rootsvn = None @@ -98,10 +101,18 @@ app.log.fatal('must run in a subversion workspace (.svn not found)') return rootsvn + def svn_root(): return os.path.abspath(os.path.dirname(svn_rootsvn())) +def svn_savediff(file, target, context=100): + path = file.path + exit_code, out = runo('svn diff --diff-cmd diff -x "-U %d" %s' % (context, path)) + open(target, 'w').write(''.join(out)) + return exit_code + + def runoe(cmd): process = popen2.Popen3(cmd, capturestderr=1) process.tochild.close() @@ -112,14 +123,17 @@ app.log.debug('run "%s" failed (%d): err=%s, out=%s' % (cmd, exit_code, err, out)) return exit_code, out, err + def runo(cmd): exit_code, out, err = runoe(cmd) return exit_code, out + def run(cmd): exit_code, out, err = runoe(cmd) return exit_code + def svn_submit_review(name, log, contents): info = svn_info() url = info.get('URL', '') Modified: trunk/CSP/tools/subset =================================================================== --- trunk/CSP/tools/subset 2004-06-05 20:48:34 UTC (rev 993) +++ trunk/CSP/tools/subset 2004-06-05 23:39:52 UTC (rev 994) @@ -32,10 +32,7 @@ # TODO # clean up error reporting of review submit -# default changeset? -# use edit function for changeset descriptions (honor save/nosave) -# a changeset diff viewer (extend describe)... maybe a textbased -# diff chooser. also need diffstats +# diffstats # work with tkdiff by piping through undiff @@ -150,16 +147,16 @@ self._date = time.time() self._pending = pending - def describe(self): - print - print 'changelist: %s' % self._name - print 'created on: %s' % self.date() - print - print '\n'.join(self._description) - print + def describe(self, outfile=sys.stdout): + print >>outfile, '' + print >>outfile, 'change set: %s' % self._name + print >>outfile, 'created on: %s' % self.date() + print >>outfile, '' + print >>outfile, '\n'.join(self._description) + print >>outfile, '' if self._files: - for file in self._files: print str(file) - print + for file in self._files: print >>outfile, str(file) + print >>outfile, '' return Result(0) def submit(self): @@ -168,7 +165,7 @@ exitcode = os.system('svn ci -m \'%s\' %s' % (description, ' '.join(files))) if exitcode != 0: - return Error('error submitting changelist') + return Error('error submitting changeset') self._pending = 0 return Result(0) @@ -185,7 +182,7 @@ if new: self._pending = 1 desc = ['<enter a description here>'] - addtext('# changelist : %s' % self._name) + addtext('# change set : %s' % self._name) addtext('# created on : %s' % self.date()) if self._pending: addtext('# status : pending') @@ -362,6 +359,73 @@ self.save() return Result(0) + def diff(self, name): + dircmd = os.environ.get('SUBSET_DIFF_DIR', '') + onecmd = os.environ.get('SUBSET_DIFF_ONE', dircmd) + cs = None + if not name: + files = filter(self._closed, sublib.svn_st()) + elif os.path.exists(name): + files = sublib.svn_st() + path = os.path.abspath(name) + files = [x for x in files if x.abspath() == path] + if not files: + print '%s unmanaged or unchanged' % name + return Result(0) + else: + cs = self.getChangeset(name) + if not cs: + return Error('no changeset "%s"' % name) + files = cs.files() + cs.describe() + if not files: return Result(0) + tmproot = '/tmp/subset.diff.%010d' % random.randint(1, 1000000000) + os.mkdir(tmproot) + cleanup = [] + singleton = not cs and (len(files) == 1) + if singleton and not onecmd: + print 'SUBSET_DIFF_ONE undefined; cannot view diff.' + return Result(1) + if not singleton and not dircmd: + print 'SUBSET_DIFF_DIR undefined; cannot view diff.' + return Result(1) + makeindex = not singleton + if makeindex: + diffindex = os.path.join(tmproot, 'index.html') + index = open(diffindex, 'w') + index.write('<html><body><small>\n') + if cs: + index.write('<h3>Changeset %s</h3>\n' % cs.name()) + index.write('<i>Created on: %s</i><p/>' % cs.date()) + for line in cs.description(): + if line.strip(): + index.write('%s ' % line) + else: + index.write('<p/>\n') + index.write('\n<p/>\n') + else: + index.write('<h3>%s</h3>' % name) + cleanup.append(diffindex) + index.write('<ul>\n') + for file in files: + outbase = file.path.replace(os.path.sep, '~') + '.diff' + outfile = os.path.join(tmproot, outbase) + cleanup.append(outfile) + sublib.svn_savediff(file, outfile) + if makeindex: + index.write('<li><a href="%s">%s</a></li>\n' % (outbase, file.path)) + if makeindex: + index.write('</ul>\n</small></body></html>') + index.close() + if singleton: + os.system('%s %s 2>/dev/null' % (onecmd, cleanup[-1])) + else: + os.system('%s %s 2>/dev/null' % (dircmd, tmproot)) + for path in cleanup: + os.unlink(path) + os.rmdir(tmproot) + return Result(0) + def opened(self, filters=None): files = sublib.svn_st() if filters: @@ -734,6 +798,25 @@ return run('describe', name) +class Diff(Command): + + def _define(self): + self._long = ('diff: generate diffs for files or changesets.\n' + 'usage: %prog diff [changeset|file]') + self._short = 'generate diffs' + self._addKeys('diff') + + def _run(self, options, args): + if len(args) > 1: + self.help() + return 1 + if len(args) == 0: + name = '' + else: + name = args[0] + return run('diff', name) + + class Help(Command): def _define(self): @@ -776,8 +859,18 @@ # register subcommands -Help(), Opened(), Changes(), Assign(), Describe(), Abandon(), Change(), Submit(), Review() +Abandon() +Assign() +Change() +Changes() +Describe() +Diff() +Help() +Opened() +Review() +Submit() + def main(args): if len(args) < 1: app.usage() |
From: <sv...@ww...> - 2004-06-05 20:48:40
|
Author: mkrose Date: 2004-06-05 13:48:34 -0700 (Sat, 05 Jun 2004) New Revision: 993 Modified: trunk/CSP/base/app.py trunk/CSP/tools/bootstrap.py Log: Minor cleanup of app and bootstrap Modified: trunk/CSP/base/app.py =================================================================== --- trunk/CSP/base/app.py 2004-06-05 20:45:58 UTC (rev 992) +++ trunk/CSP/base/app.py 2004-06-05 20:48:34 UTC (rev 993) @@ -99,12 +99,18 @@ Start the application. Parses arguments, sets up logging, and calls main(args). + + Args: + disable_interspersed_args: if true, command line flags must preceed + positional arguments. otherwise, command line flags can be mixed + with positional arguments. """ if disable_interspersed_args: opt.disable_interspersed_args() result = 0 try: - frame = inspect.stack()[-1][0] + stack = inspect.stack() + frame = stack[1][0] name = frame.f_globals.get('__name__', '') if name == '__main__': doc = frame.f_globals.get('__doc__', None) Modified: trunk/CSP/tools/bootstrap.py =================================================================== --- trunk/CSP/tools/bootstrap.py 2004-06-05 20:45:58 UTC (rev 992) +++ trunk/CSP/tools/bootstrap.py 2004-06-05 20:48:34 UTC (rev 993) @@ -1,17 +1,15 @@ import sys import os.path -if not getattr(sys, 'CSP', 0): - +try: + import CSP +except: dn = os.path.dirname root = dn(dn(dn(__file__))) sys.path.insert(0, root) - try: import CSP except: print 'Unable to import the main CSP module. Check that you have' print 'a complete working copy.' sys.exit(1) - - sys.CSP = root |
From: <sv...@ww...> - 2004-06-05 20:46:06
|
Author: mkrose Date: 2004-06-05 13:45:58 -0700 (Sat, 05 Jun 2004) New Revision: 992 Added: trunk/CSP/tools/pyrun trunk/CSP/tools/pyrun.stub Log: Added a tool for bundling pure python modules together into a single application file. Linux-specific for now. Added: trunk/CSP/tools/pyrun =================================================================== --- trunk/CSP/tools/pyrun 2004-06-04 10:24:47 UTC (rev 991) +++ trunk/CSP/tools/pyrun 2004-06-05 20:45:58 UTC (rev 992) @@ -0,0 +1,195 @@ +#!/usr/bin/python +# +# Copyright 2004 Mark Rose <mk...@us...> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" +%(prog)s: Construct bundled python applications. + +Takes python script as input and generates a single python program that +contains all necessary extension modules outside of the standard library. + +Caveats: + * A full python installation is still required to run the resulting program. + * Impure python extension modules (shared libraries) are not yet supported. + * The startup stub is currently linux-specific. + +Usage: %(prog)s [options] script +""" + +import sys +import os +import re +import os.path +import zipfile +from modulefinder import ModuleFinder + +import bootstrap +from CSP.base import app + +DEFAULT_STUB = 'pyrun.stub' + + +def main(args): + if len(args) != 1: + app.usage() + return 1 + + program = os.path.abspath(args[0]) + target = app.options.output + if not target: + target =os.path.basename(program) + '.run' + + assemble(program, target) + + +def findCustomModules(modules): + re_stdlib = re.compile(r'[/\\][pP]ython[\.0-9]*[/\\]') + custom = [] + for mod in modules: + file = mod.__file__ + if file is None: continue + match = re_stdlib.search(file) + if match is not None: + if not file[match.end():].startswith('site-packages'): continue + if file.lower().endswith('.so') or file.lower().endswith('.dll'): + print 'WARNING: skipping impure python module (%s)' % file + continue + custom.append(mod) + return custom + + +def findDependencies(program, path): + mf = ModuleFinder(path) + mf.run_script(program) + custom = findCustomModules(mf.modules.values()) + names = [x.__name__ for x in custom] + missing = {} + ignore = app.options.ignore + for name, calldict in mf.badmodules.items(): + for caller in calldict.keys(): + if caller in names: + if not name in ignore: + missing.setdefault(name, []).append(caller) + for name, callers in missing.items(): + print 'WARNING: module %s not found (called by %s)' % (name, ', '.join(callers)) + if missing: + print 'ERROR: some modules were not found.' + print 'You may need to use the --addpath or --ignore flags.' + sys.exit(1) + return custom + + +def makeZip(zipname, program, modules, path): + out = zipfile.PyZipFile(zipname, 'w', compression=zipfile.ZIP_DEFLATED) + for module in modules: + name = module.__name__ + file = module.__file__ + basename = '' + for p in path: + if file.startswith(p): + basename = os.path.dirname(file)[len(p):] + break + if os.path.isabs(basename): + basename = basename[1:] + if file == program: + f = open('pyx_program.py', 'w') + # big ol' hack. insert some magic to make the main script look like it + # was run directly instead of imported. better solutions welcome... + inject = 1 + for line in open(program): + if (inject and (line.startswith('import') or line.startswith('app.start(') or + line.startswith('if __name__ =='))): + inject = 0 + print >>f, "import sys; sys.modules['__main__'] = sys.modules[__name__]; __name__ = '__main__';" + print >>f, line, + f.close() + out.writepy('pyx_program.py') + for ext in ('.py', '.pyc', '.pyo'): + pyx_name = 'pyx_program' + ext + if os.path.exists(pyx_name): os.unlink(pyx_name) + elif file.endswith('.py'): + out.writepy(file, basename) + if os.path.dirname(file) == os.path.dirname(program): + out.writepy(file) + else: + out.write(file, os.path.basename(file)) + if not app.options.quiet: + print '.. Added %s (%s)' % (name, file) + out.close() + + +def addStub(stub, tmpname, target): + zip = open(tmpname, 'r') + stub = open(stub, 'r') + out = open(target, 'w') + out.write(stub.read()) + out.write(zip.read()) + stub.close() + zip.close() + out.close() + + +def getPath(program): + path = sys.path[:] + path[0] = os.path.dirname(program) + addpaths = app.options.addpath[:] + addpaths.reverse() + for addpath in addpaths: + path.insert(0, os.path.abspath(addpath)) + return path + + +def assemble(program, target): + path = getPath(program) + + stub = app.options.stub + if not os.path.exists(stub): + print 'Stub file %s not found, aborting' % stub + sys.exit(1) + + if os.path.exists(target) and not app.options.force: + print '%s already exists, aborting' % target + sys.exit(1) + + if not app.options.quiet: + print 'Finding dependencies' + + modules = findDependencies(program, path) + + if not app.options.quiet: + print 'Creating executable %s' % target + + tmpname = target + "~" + makeZip(tmpname, program, modules, path) + addStub(stub, tmpname, target) + + os.unlink(tmpname) + os.chmod(target, 0755) + + if not app.options.quiet: + print 'Done.' + + +app.addOption('--addpath', metavar='PATH', action='append', default=[], help='add path to sys.path') +app.addOption('-q', '--quiet', action='store_true', default=False, help='quiet mode (less verbose)') +app.addOption('--output', metavar='FILE', default=None, help='specify output file') +app.addOption('-f', '--force', action='store_true', default=False, help='overwrite existing output file') +app.addOption('--stub', metavar='STUBFILE', default=DEFAULT_STUB, help='stub file to use') +app.addOption('--ignore', metavar='MODULE', action='append', default=['os.path'], help='ignore unresolved module dependency') + +app.start() + Property changes on: trunk/CSP/tools/pyrun ___________________________________________________________________ Name: svn:executable + * Added: trunk/CSP/tools/pyrun.stub =================================================================== --- trunk/CSP/tools/pyrun.stub 2004-06-04 10:24:47 UTC (rev 991) +++ trunk/CSP/tools/pyrun.stub 2004-06-05 20:45:58 UTC (rev 992) @@ -0,0 +1 @@ +python2.3 -c "import sys; sys.path[0]='$0'; sys.argv[0]='$0'; import pyx_program" ${1+"$@"}; exit $? |
From: <sv...@ww...> - 2004-06-04 10:24:53
|
Author: mkrose Date: 2004-06-04 03:24:47 -0700 (Fri, 04 Jun 2004) New Revision: 991 Added: trunk/CSP/CSPChunkLod/lib/ Log: add lib directory |
From: <sv...@ww...> - 2004-06-04 10:17:08
|
Author: mkrose Date: 2004-06-04 03:17:02 -0700 (Fri, 04 Jun 2004) New Revision: 990 Modified: trunk/CSP/SimData/CHANGES.current Log: Update changelog. Modified: trunk/CSP/SimData/CHANGES.current =================================================================== --- trunk/CSP/SimData/CHANGES.current 2004-06-04 07:57:22 UTC (rev 989) +++ trunk/CSP/SimData/CHANGES.current 2004-06-04 10:17:02 UTC (rev 990) @@ -1,6 +1,11 @@ Version 0.4.0 (in progress) =========================== +2004-06-03: onsight + * Small cleanups in Ref.h. More substantive changes still + to come. Adds a new header Properties.h. +===> WINDOWS users please test. + 2004-05-28: wolverine * It was determined that Vector3 and Quad have extra bytes to handle there virtual function tables. The networking |
From: <sv...@ww...> - 2004-06-04 07:58:08
|
Author: mkrose Date: 2004-06-04 00:57:22 -0700 (Fri, 04 Jun 2004) New Revision: 989 Added: trunk/CSP/SimData/Include/SimData/Properties.h Modified: trunk/CSP/SimData/Include/SimData/Link.h trunk/CSP/SimData/Include/SimData/Path.h trunk/CSP/SimData/Include/SimData/Ref.h trunk/CSP/SimData/Source/SConscript trunk/CSP/SimData/setup.py Log: Small cleanups for reference counting classes (more to come). Modified: trunk/CSP/SimData/Include/SimData/Link.h =================================================================== --- trunk/CSP/SimData/Include/SimData/Link.h 2004-06-04 07:54:54 UTC (rev 988) +++ trunk/CSP/SimData/Include/SimData/Link.h 2004-06-04 07:57:22 UTC (rev 989) @@ -155,7 +155,7 @@ inline void _assign_safe(Object* ptr) { _release(); _update(ptr); - if (!isNull()) _reference->_ref(); + if (!isNull()) _reference->_incref(); } /** Rebind to a new object, without testing for type compatibility. @@ -166,14 +166,14 @@ inline void _assign_fast(Object *ptr) { _release(); _reference = ptr; - if (!isNull()) _reference->_ref(); + if (!isNull()) _reference->_incref(); } /** Rebind to null. */ inline void _release() { if (!isNull()) { - _reference->_deref(); + _reference->_decref(); _reference = 0; } } Modified: trunk/CSP/SimData/Include/SimData/Path.h =================================================================== --- trunk/CSP/SimData/Include/SimData/Path.h 2004-06-04 07:54:54 UTC (rev 988) +++ trunk/CSP/SimData/Include/SimData/Path.h 2004-06-04 07:57:22 UTC (rev 989) @@ -275,7 +275,7 @@ inline void _assign_safe(Object* ptr) { _release(); _update(ptr); - if (!isNull()) _reference->_ref(); + if (!isNull()) _reference->_incref(); } /** @@ -287,7 +287,7 @@ inline void _assign_fast(Object *ptr) { _release(); _reference = ptr; - if (!isNull()) _reference->_ref(); + if (!isNull()) _reference->_incref(); } /** @@ -295,7 +295,7 @@ */ inline void _release() { if (!isNull()) { - _reference->_deref(); + _reference->_decref(); _reference = 0; } } Added: trunk/CSP/SimData/Include/SimData/Properties.h =================================================================== --- trunk/CSP/SimData/Include/SimData/Properties.h 2004-06-04 07:54:54 UTC (rev 988) +++ trunk/CSP/SimData/Include/SimData/Properties.h 2004-06-04 07:57:22 UTC (rev 989) @@ -0,0 +1,65 @@ +/* SimData: Data Infrastructure for Simulations + * Copyright (C) 2002-2004 Mark Rose <mk...@us...> + * + * This file is part of SimData. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +/** + * @file Properties.h + * + * Inheritable class properties. + */ + + +#ifndef __SIMDATA_PROPERTIES_H__ +#define __SIMDATA_PROPERTIES_H__ + +#include <SimData/Namespace.h> +#include <SimData/Export.h> + + +NAMESPACE_SIMDATA + + +/** Inheritable property for classes that cannot be copied. + * + * @author Mark Rose <mk...@us...> + */ +class NonCopyable { +protected: + NonCopyable() { } +private: + NonCopyable(NonCopyable const &); + void operator = (NonCopyable const &); +}; + + +/** Inheritable property for classes that cannot be (publicly) constructed. + * + * @author Mark Rose <mk...@us...> + */ +class NonConstructable: public NonCopyable { +private: + NonConstructable(); +}; + +NAMESPACE_SIMDATA_END + + +#endif //__SIMDATA_OBJECT_H__ + Modified: trunk/CSP/SimData/Include/SimData/Ref.h =================================================================== --- trunk/CSP/SimData/Include/SimData/Ref.h 2004-06-04 07:54:54 UTC (rev 988) +++ trunk/CSP/SimData/Include/SimData/Ref.h 2004-06-04 07:57:22 UTC (rev 989) @@ -37,6 +37,7 @@ #include <SimData/Export.h> #include <SimData/ExceptionBase.h> #include <SimData/Log.h> +#include <SimData/Properties.h> NAMESPACE_SIMDATA @@ -82,7 +83,7 @@ /** Create a new reference. */ Ref(T* ptr): _reference(ptr) { - if (ptr) ptr->_ref(); + if (ptr) ptr->_incref(); } /** Light-weight copy with reference counting. @@ -97,7 +98,7 @@ Ref(Ref<Q> const & r): _reference(0) { Q *rp = r.get(); if (rp != 0) { - //rp->_ref(); + //rp->_incref(); //_reference = static_cast<T*>(rp); _rebind(rp); } @@ -106,14 +107,14 @@ /** Light-weight copy with reference counting. */ Ref(Ref const & r): _reference(r._reference) { - if (_reference != 0) _reference->_ref(); + if (_reference != 0) _reference->_incref(); } /** Decrement the reference count, and potentially destroy * the referenced object. */ ~Ref() { - if (_reference) _reference->_deref(); + if (_reference) _reference->_decref(); } /** Returns true if this is the only reference. @@ -167,7 +168,7 @@ */ inline void *operator=(void *ptr) { assert(ptr==0); - if (_reference != 0) _reference->_deref(); + if (_reference != 0) _reference->_decref(); _reference = 0; return ptr; } @@ -238,8 +239,8 @@ */ template <class Q> void _rebind(Q* ptr) { - if (ptr) ptr->_ref(); - if (_reference != 0) _reference->_deref(); + if (ptr) ptr->_incref(); + if (_reference != 0) _reference->_decref(); _reference = dynamic_cast<T*>(ptr); if (_reference == 0 && ptr != 0) { SIMDATA_LOG(LOG_ALL, LOG_ERROR, "simdata::Ref() assignment: incompatible types (dynamic cast failed)."); @@ -259,19 +260,18 @@ * * @author Mark Rose <mr...@st...> */ -class SIMDATA_EXPORT Referenced { +class SIMDATA_EXPORT Referenced: public NonCopyable { template <class T> friend class Ref; friend class ReferencePointer; -public: +protected: Referenced(): __count(0) {} -protected: /** @todo This dtor should be eliminated eventually, or at * least made non-virtual if we can be sure that Referenced - * derived objects will never be deleted via a Referenced*. - * Since Referenced::_deref() currently handles deletion, + * derived objects will never be deleted via a Referenced*. + * Since Referenced::_decref() currently handles deletion, * this would require moving the deletion responsibility to * Ref<>, and declaring a Ref<Referenced> specialization for * preventation. --MR @@ -283,23 +283,14 @@ } private: - inline void _ref() const { ++__count; } - - inline void _deref() const { + inline void _incref() const { ++__count; } + inline void _decref() const { if (--__count <= 0) { delete this; } } inline unsigned _count() const { return __count; } - mutable unsigned __count; - - Referenced(Referenced const &); //: __count(0) {} - -#ifndef SWIG - inline Referenced& operator=(Referenced const &);// { return *this; } -#endif // SWIG - }; Modified: trunk/CSP/SimData/Source/SConscript =================================================================== --- trunk/CSP/SimData/Source/SConscript 2004-06-04 07:54:54 UTC (rev 988) +++ trunk/CSP/SimData/Source/SConscript 2004-06-04 07:57:22 UTC (rev 989) @@ -61,6 +61,7 @@ osg.h Path.h PTS.h + Properties.h Quat.h Random.h Real.h Modified: trunk/CSP/SimData/setup.py =================================================================== --- trunk/CSP/SimData/setup.py 2004-06-04 07:54:54 UTC (rev 988) +++ trunk/CSP/SimData/setup.py 2004-06-04 07:57:22 UTC (rev 989) @@ -313,6 +313,7 @@ "osg.h", "Path.h", "PTS.h", + "Properties.h", "Quat.h", "Random.h", "Real.h", |
From: <sv...@ww...> - 2004-06-04 07:58:03
|
Author: mkrose Date: 2004-06-04 00:54:54 -0700 (Fri, 04 Jun 2004) New Revision: 988 Modified: trunk/CSP/tools/subset Log: Properly escape changelist descriptions when submitting. Modified: trunk/CSP/tools/subset =================================================================== --- trunk/CSP/tools/subset 2004-06-04 07:51:27 UTC (rev 987) +++ trunk/CSP/tools/subset 2004-06-04 07:54:54 UTC (rev 988) @@ -164,8 +164,9 @@ def submit(self): files = map(lambda x: x.abspath(), self._files) + description = '\n'.join(self._description).replace("'", "'\"'\"'") exitcode = os.system('svn ci -m \'%s\' %s' % - ('\n'.join(self._description), ' '.join(files))) + (description, ' '.join(files))) if exitcode != 0: return Error('error submitting changelist') self._pending = 0 |
From: <sv...@ww...> - 2004-06-03 06:36:36
|
Author: mkrose Date: 2004-06-02 23:36:28 -0700 (Wed, 02 Jun 2004) New Revision: 986 Modified: trunk/CSP/tools/sublib.py Log: Add copyright notice and module comment to sublib.py Modified: trunk/CSP/tools/sublib.py =================================================================== --- trunk/CSP/tools/sublib.py 2004-06-03 06:28:45 UTC (rev 985) +++ trunk/CSP/tools/sublib.py 2004-06-03 06:36:28 UTC (rev 986) @@ -1,3 +1,29 @@ +#!/usr/bin/python +# +# Copyright 2004 Mark Rose <mk...@us...> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +""" +Trivial library for accessing subversion via the command line +tool. This should really be replaced by either the subversion +python bindings (or a thin wrapper around them) once they reach +a stable state with decent documentation. +""" + import os import os.path import popen2 |
From: <sv...@ww...> - 2004-06-03 06:28:52
|
Author: mkrose Date: 2004-06-02 23:28:45 -0700 (Wed, 02 Jun 2004) New Revision: 985 Modified: trunk/CSP/tools/subset Log: Delete changelists after submit. Modified: trunk/CSP/tools/subset =================================================================== --- trunk/CSP/tools/subset 2004-06-03 06:25:57 UTC (rev 984) +++ trunk/CSP/tools/subset 2004-06-03 06:28:45 UTC (rev 985) @@ -446,7 +446,7 @@ if not result.ok: return result result = cs.submit() if result.ok: - #del self._sets[name] + del self._sets[name] self.save() return result |
From: <sv...@ww...> - 2004-06-03 06:26:04
|
Author: mkrose Date: 2004-06-02 23:25:57 -0700 (Wed, 02 Jun 2004) New Revision: 984 Modified: trunk/CSP/tools/subset Log: Fix bad method name for editing changelists during submit. Modified: trunk/CSP/tools/subset =================================================================== --- trunk/CSP/tools/subset 2004-06-03 06:22:26 UTC (rev 983) +++ trunk/CSP/tools/subset 2004-06-03 06:25:57 UTC (rev 984) @@ -442,7 +442,7 @@ if not result.ok: return result cs = result.value else: - result = self.edit(name) + result = self.change(name) if not result.ok: return result result = cs.submit() if result.ok: |
From: <sv...@ww...> - 2004-06-03 06:22:36
|
Author: mkrose Date: 2004-06-02 23:22:26 -0700 (Wed, 02 Jun 2004) New Revision: 983 Added: trunk/CSP/__init__.py trunk/CSP/base/ trunk/CSP/base/__init__.py trunk/CSP/base/app.py trunk/CSP/base/applog.py trunk/CSP/tools/ trunk/CSP/tools/__init__.py trunk/CSP/tools/bootstrap.py trunk/CSP/tools/sublib.py trunk/CSP/tools/subset Log: * Create a python package space for CSP in the trunk workspace. * Add tool for changeset management under subversion. * Add helper modules that can be used by other python applications in CSP. The python path bootstrapping is a bit primitive / brittle at the moment. Adding an installer, and/or a one-time workspace setup script would help a lot. Added: trunk/CSP/__init__.py =================================================================== --- trunk/CSP/__init__.py 2004-05-31 04:10:07 UTC (rev 982) +++ trunk/CSP/__init__.py 2004-06-03 06:22:26 UTC (rev 983) @@ -0,0 +1 @@ +CSP = 1 Added: trunk/CSP/base/__init__.py =================================================================== Added: trunk/CSP/base/app.py =================================================================== --- trunk/CSP/base/app.py 2004-05-31 04:10:07 UTC (rev 982) +++ trunk/CSP/base/app.py 2004-06-03 06:22:26 UTC (rev 983) @@ -0,0 +1,145 @@ +# Copyright 2004 Mark Rose <mk...@us...> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" +Define a standard framework for running python applications. + +Applicitions using this module should be structured as follows: + + #! /.../pythonX + # copyright notices + docstring (for usage) + imports + classes and functions + def main(args): ... + app.start() + +The docstring serves as the usage text that is printed when --help is +specified. It can include %(prog)s and %(progpath)s substitutions. + +main() is the main entry point for the application. Non-flag command +line arguments are passed in (excluding the program name), and the +return value serves as the exit code for the application. The program +name and absolute path can be accessed using app.programName() and +app.programPath(), respectively. Command line flags are specified +using app.addOption(...) (same arguments as optparse add_option), and +accessed by app.options.<flagname>. + +The call to app.start() can optionally be placed inside an if __name__ +== '__main__' block. This is not necessary, however, since app.start() +does nothing if called from a non-main module. +""" + +import sys +import os.path +import inspect +import optparse +import exceptions +import logging +import applog + + +class CustomUsageFormatter(optparse.IndentedHelpFormatter): + def format_usage(self, usage): + return usage % {'prog' : programName(), 'progpath' : programPath()} + +log = logging.getLogger('app') + +def _fatal(msg, *args, **kw): + """ + Log a critical message and terminate the application, with an optional exit + code. + + Args: + same as logging.critical() + optional keyword argument 'exit_code' to set the exit code (default 1). + """ + log.critical(msg, *args, **kw) + code = kw.get('exit_code', 1) + sys.exit(code) + +# override logging.fatal, which is deprecated and equivalent to critical(). +# the replacement logs a critical message and terminates the application. +log.fatal = _fatal + +opt = optparse.OptionParser(usage='', formatter=CustomUsageFormatter()) +addOption = opt.add_option + +addOption('-v', '--verbose', default='info', type='string', metavar='<level>', + help='set verbosity level (numeric, or by name)') +addOption('--logfile', default='', type='string', help='log file (default stderr)') + +def usage(): + """Print usage to stdout.""" + opt.print_help() + +def programPath(): + """Return the absolute path of the application program.""" + return os.path.abspath(sys.argv[0]) + +def programName(): + """Return the basename of the application program.""" + return os.path.basename(sys.argv[0]) + +def start(disable_interspersed_args=0): + """ + Start the application. + + Parses arguments, sets up logging, and calls main(args). + """ + if disable_interspersed_args: + opt.disable_interspersed_args() + result = 0 + try: + frame = inspect.stack()[-1][0] + name = frame.f_globals.get('__name__', '') + if name == '__main__': + doc = frame.f_globals.get('__doc__', None) + opt.set_usage(doc) + main = frame.f_globals.get('main', None) + global options + options, args = opt.parse_args() + if options.logfile: + logfile = open(options.logfile, 'w') + else: + logfile = sys.stderr + loghandler = logging.StreamHandler(logfile) + loghandler.setFormatter(applog.formatter) + loghandler.setLevel(logging.NOTSET) + log.addHandler(loghandler) + try: + level = int(options.verbose) + except ValueError: + levelname = options.verbose.upper() + level = logging._levelNames.get(levelname, -1) + if level == -1: + levels = logging._levelNames.keys() + levels = [x.lower() for x in levels if not isinstance(x, int)] + levels.sort() + print >>sys.stderr, 'logging verbosity "%s" unrecognized; valid level names are:' % options.verbose + print >>sys.stderr, ' (' + ','.join(levels) + ')' + sys.exit(1) + log.setLevel(level) + if main: result = main(args) + except KeyboardInterrupt: + log.exception('caught keyboard interrept; aborting.') + except exceptions.SystemExit, e: + raise e + except Exception, e: + log.exception('caught exception %s; aborting' % e) + sys.exit(result) + + Added: trunk/CSP/base/applog.py =================================================================== --- trunk/CSP/base/applog.py 2004-05-31 04:10:07 UTC (rev 982) +++ trunk/CSP/base/applog.py 2004-06-03 06:22:26 UTC (rev 983) @@ -0,0 +1,31 @@ +# Copyright 2004 Mark Rose <mk...@us...> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" +Define standard formating for application logs. +""" + +import sys +import logging + +logging.addLevelName(logging.DEBUG, 'D') +logging.addLevelName(logging.INFO, 'I') +logging.addLevelName(logging.WARNING, 'W') +logging.addLevelName(logging.ERROR, 'E') +logging.addLevelName(logging.CRITICAL, 'C') + +formatter = logging.Formatter('%(asctime)s%(levelname)s_%(module)s.%(lineno)d %(message)s', '%m%d%H%M%S') + Added: trunk/CSP/tools/__init__.py =================================================================== Added: trunk/CSP/tools/bootstrap.py =================================================================== --- trunk/CSP/tools/bootstrap.py 2004-05-31 04:10:07 UTC (rev 982) +++ trunk/CSP/tools/bootstrap.py 2004-06-03 06:22:26 UTC (rev 983) @@ -0,0 +1,17 @@ +import sys +import os.path + +if not getattr(sys, 'CSP', 0): + + dn = os.path.dirname + root = dn(dn(dn(__file__))) + sys.path.insert(0, root) + + try: + import CSP + except: + print 'Unable to import the main CSP module. Check that you have' + print 'a complete working copy.' + sys.exit(1) + + sys.CSP = root Added: trunk/CSP/tools/sublib.py =================================================================== --- trunk/CSP/tools/sublib.py 2004-05-31 04:10:07 UTC (rev 982) +++ trunk/CSP/tools/sublib.py 2004-06-03 06:22:26 UTC (rev 983) @@ -0,0 +1,160 @@ +import os +import os.path +import popen2 +import re +import time + +from CSP.base import app + +class File: + ADD = 'ADD' + DEL = 'DEL' + MOD = 'MOD' + + def __init__(self, path, root, mode): + self.mode = mode + self.root = root + self.path = path + + def __str__(self): + return '(%s) //%s' % (self.mode, self.path) + + def abspath(self): + return os.path.join(self.root, self.path) + + +def svn_info(): + st = os.popen('svn info').readlines() + info = {} + for line in st: + line = line.strip() + idx = line.find(':') + if idx < 0: continue + info[line[:idx]] = line[idx+1:].strip() + return info + +def svn_st(files=None): + if not files: files = [] + st = os.popen('svn st %s' % ' '.join(files)).readlines() + root = svn_root() + files = [] + for line in st: + path = line[1:].strip() + abspath = os.path.abspath(path) + assert(abspath.startswith(root)) + relpath = abspath[len(root):] + if os.path.isabs(relpath): + relpath = relpath[1:] + basename = os.path.basename(path) + if basename.startswith('.svn'): continue + if line.startswith('M'): mode = File.MOD + elif line.startswith('A'): mode = File.ADD + elif line.startswith('D'): mode = File.DEL + else: continue + files.append(File(relpath, root, mode)) + return files + +#def svn_info(path): +# info = os.popen('svn info %s' % path) +# app.log.info(info.readlines()) + +def svn_rootsvn(): + path = '.svn' + rootsvn = None + while os.path.exists(path): + rootsvn = path + path = os.path.join('..', path) + if not rootsvn: + app.log.fatal('must run in a subversion workspace (.svn not found)') + return rootsvn + +def svn_root(): + return os.path.abspath(os.path.dirname(svn_rootsvn())) + + +def runoe(cmd): + process = popen2.Popen3(cmd, capturestderr=1) + process.tochild.close() + out = process.fromchild.readlines() + err = process.childerr.readlines() + exit_code = process.wait() + if exit_code: + app.log.debug('run "%s" failed (%d): err=%s, out=%s' % (cmd, exit_code, err, out)) + return exit_code, out, err + +def runo(cmd): + exit_code, out, err = runoe(cmd) + return exit_code, out + +def run(cmd): + exit_code, out, err = runoe(cmd) + return exit_code + +def svn_submit_review(name, log, contents): + info = svn_info() + url = info.get('URL', '') + if not url: + app.log.fatal('unable to locate repository URL') + root = os.path.abspath(svn_rootsvn()) + targetdir = 'reviews' + target = os.path.join(root, '.%s' % targetdir) + targetfile = os.path.join(target, 'change') + if os.path.exists(targetfile): + os.unlink(targetfile) + while 1: + source = os.path.join(url, targetdir) + #print 'svn co %s %s 2>/dev/null' % (source, target) + exit_code = run('svn co %s %s' % (source, target)) + if not exit_code: break + app.log.debug('checkout of %s to %s failed.' % (source, target)) + parent = os.path.dirname(url) + if parent == url: + app.log.fatal('could not find review path; have you created one?') + url = parent + if not os.path.exists(targetfile): + app.log.fatal('could not find review path; have you created one?') + app.log.debug('checked out review path from %s' % source) + app.log.debug('submitting changelist %s for review' % name) + while 1: + exit_code = run('svn rm %s' % targetfile) + if exit_code: + app.log.error('unable to remove %s' % targetfile) + break + f = open(targetfile, 'w') + f.write(contents) + f.close() + exit_code = run('svn add %s' % targetfile) + if exit_code: + app.log.error('unable to add %s' % targetfile) + break + exit_code, out = runo('svn ci -m "%s" %s' % (log, targetfile)) + if not exit_code: + ci_log = out + break + app.log.info('failed to submit changelist %s for review: %s' % (name, str(ci))) + exit_code = run('svn revert %s' % targetfile) + if exit_code: + app.log.error('unable to revert changes to %s in order to retry commit' % targetfile) + break + time.sleep(1) + exit_code = run('svn up %s' % targetfile) + if exit_code: + app.log.error('unable to update %s in order to retry commit' % targetfile) + break + if exit_code: + print 'Failed to submit changelist %s for review; see log for details.' % name + return 1 + rev = 0 + re_rev = re.compile(r'Committed revision (\d+)') + for line in ci_log: + m = re_rev.match(line) + if m is not None: + rev = int(m.group(1)) + break + if rev: + print "Changelist %s submitted for review; review id %d." % (name, rev) + else: + print 'Changelist %s submitted for review, but could not determine a review number' + print 'Try running "svn log %s"' % source + return 0 + Added: trunk/CSP/tools/subset =================================================================== --- trunk/CSP/tools/subset 2004-05-31 04:10:07 UTC (rev 982) +++ trunk/CSP/tools/subset 2004-06-03 06:22:26 UTC (rev 983) @@ -0,0 +1,789 @@ +#!/usr/bin/python +# +# Copyright 2004 Mark Rose <mk...@us...> +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +""" +Changeset manager for subversion (http://tigris.subversion.org). + +Copyright 2004 Mark Rose. This program is free software; you can +redistributed 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. + +Usage: %(prog)s [options] command [args...] + +Run "%(prog)s help <command>" for help on a specific command. +""" + +# TODO +# clean up error reporting of review submit +# default changeset? +# use edit function for changeset descriptions (honor save/nosave) +# a changeset diff viewer (extend describe)... maybe a textbased +# diff chooser. also need diffstats +# work with tkdiff by piping through undiff + + +import sys +import os +import os.path +import glob +import stat +import random +import tempfile +import optparse +import pickle +import zipfile +import StringIO +import time + +# setup CSP +import bootstrap + +from CSP.tools import sublib +from CSP.base import app + + +def sendmail(sender, recipients, subject, body, attachments=None): + import email + import email.MIMEMultipart + import email.MIMEText + import email.MIMEBase + import smtplib + import mimetypes + outer = email.MIMEMultipart.MIMEMultipart() + outer['Subject'] = subject + outer['To'] = ', '.join(recipients) + outer['From'] = sender + outer.preamble = 'You need a MIME-aware mail reader to view this message.\n' + outer.epilogue = '' + outer.attach(email.MIMEText.MIMEText(body)) + if attachments is not None: + for name, content in attachments: + ctype, encoding = mimetypes.guess_type(name) + if ctype is None or encoding is not None: + ctype = 'application/octet-stream' + maintype, subtype = ctype.split('/') + attachment = email.MIMEBase.MIMEBase(maintype, subtype) + attachment.set_payload(content) + email.Encoders.encode_base64(attachment) + attachment.add_header('Content-Disposition', 'attachment', filename=name) + outer.attach(attachment) + s = smtplib.SMTP() + s.connect() + try: + s.sendmail(sender, recipients, outer.as_string()) + except smtplib.SMTPException, e: + return Error('error sending message: %s' % e.smtp_error) + s.close() + return Result(0) + +def edit(text, cursor=1): + tmpname = '.svn.cs.%d' % random.randint(0,100000000) + tmppath = os.path.join(tempfile.gettempdir(), tmpname) + tmpfile = os.fdopen(os.open(tmppath, os.O_CREAT|os.O_WRONLY|os.O_EXCL), 'w') + tmpfile.write(text) + tmpfile.close() + mtime = os.stat(tmppath)[stat.ST_MTIME] + os.system('vi +%d %s' % (cursor, tmppath)) + if mtime == os.stat(tmppath)[stat.ST_MTIME]: + return Result(0) + saved = ''.join(open(tmppath).readlines()) + os.unlink(tmppath) + return Result(saved) + + +class Filter: + def __init__(self, path): + self._sub = 0 + if path.endswith('...'): + path = path[:-3] + self._sub = 1 + self._abs = os.path.abspath(path) + def __call__(self, file): + path = file.abspath() + dirname = os.path.dirname(path) + if self._sub: + return dirname.startswith(self._abs) + else: + return dirname == self._abs + +class Result: + + def __init__(self, value, error=''): + self.value = value + self.error = error + self.ok = not error + + def __str__(self): + if self.error: + return 'error: %s' % self.error + else: + return 'result: %s' % self.value + + +def Error(msg): + return Result(None, error=msg) + + +class Changeset: + + def __init__(self, name, files, pending=0): + self._name = name + self._description = [] + self._files = files + self._date = time.time() + self._pending = pending + + def describe(self): + print + print 'changelist: %s' % self._name + print 'created on: %s' % self.date() + print + print '\n'.join(self._description) + print + if self._files: + for file in self._files: print str(file) + print + return Result(0) + + def submit(self): + files = map(lambda x: x.abspath(), self._files) + exitcode = os.system('svn ci -m \'%s\' %s' % + ('\n'.join(self._description), ' '.join(files))) + if exitcode != 0: + return Error('error submitting changelist') + self._pending = 0 + return Result(0) + + def edit(self, new=0): + if not hasattr(self, '_date'): + self._date = time.time() + info = sublib.svn_info() + URL = info.get('URL', '') + rev = info.get('Revision', '') + desc = self._description + cursor = 5 + text = [] + addtext = text.append + if new: + self._pending = 1 + desc = ['<enter a description here>'] + addtext('# changelist : %s' % self._name) + addtext('# created on : %s' % self.date()) + if self._pending: + addtext('# status : pending') + else: + addtext('# status : submitted') + if URL: + addtext('# repository : %s' % URL) + cursor += 1 + if rev: + addtext('# revision : %s' % rev) + cursor += 1 + addtext('') + addtext('[description]') + text += desc + addtext('') + addtext('[files]') + fileref = {} + for file in self._files: + mode = file.mode + path = file.path + addtext(' //%s # %s' % (path, mode.lower())) + fileref[path] = file + text = '\n'.join(text) + result = edit(text, cursor) + if not result.ok: + return Error('error editing description, aborting') + if not result.value: + return Error('description unchanged, aborting') + lines = result.value.split('\n') + state = 'description' + description = [] + fileset = {} + for line in lines: + line = line.strip() + if state == 'description' and line == '[description]': + state = 'desc' + elif state == 'desc': + if line == '[files]': + state = 'files' + else: + description.append(line) + elif state == 'files': + if line: + idx = line.find('#') + if idx >= 0: + line = line[:idx] + path = line.strip() + assert path.startswith('//') + path = path[2:] + file = fileref.get(path, 0) + assert file + assert not path in fileset.keys() + fileset[path] = file + if description == ['<enter a description here>', '']: + return Error('description unchanged, aborting') + idx = 0 + description.reverse() + for line in description: + if line.strip(): break + idx = idx + 1 + description.reverse() + description = map(lambda x: x.rstrip(), description[:-idx]) + self._description = description + self._files = fileset.values() + return Result(0) + + def _fileIndex(self): + index = {} + for file in self._files: + index[file.abspath()] = file + return index + + def removeFile(self, file): + index = self._fileIndex() + abspath = file.abspath() + file = index.get(abspath, None) + if not file: + return Error('file not found in changeset %s' % self._name) + self._files.remove(file) + return Result(file) + + def addFile(self, file): + index = self._fileIndex() + abspath = file.abspath() + if index.get(abspath, None): + return Error('file already in changeset %s' % self._name) + self._files.append(file) + + def isPending(self): + return self._pending + + def name(self): + return self._name + + def date(self): + return time.ctime(self._date) + + def localtime(self): + return time.localtime(self._date) + + def description(self): + return self._description[:] + + def files(self): + return self._files[:] + + def datecmp(x, y): + return cmp(x._date, y._date) + + datecmp = staticmethod(datecmp) + + +class Workspace: + + def __init__(self, rootsvn=''): + self._sets = {} + self._files = {} + if not rootsvn: rootsvn = sublib.svn_rootsvn() + self._load(rootsvn) + + def _load(self, rootsvn): + ws = os.path.join(rootsvn, '.workspace') + if os.path.exists(ws): + file = open(ws) + wsp = pickle.load(file) + self._sets = wsp.sets + for set in self._sets.values(): + for file in set._files: + abspath = file.abspath() + assert(not self._files.get(abspath, 0)) + self._files[abspath] = set + self._rootsvn = rootsvn + self._ws = ws + + def _save(self): + file = open(self._ws, 'w') + pickle.dump(self, file) + + def __getstate__(self): + return {'sets' : self._sets } + + def getChangeset(self, name): + return self._sets.get(name, None) + + def _closed(self, file): + abspath = file.abspath() + return not self._files.has_key(abspath) + + def assign(self, name, files): + if name == 'default': + dest = None + else: + dest = self.getChangeset(name) + if not dest: + return Error('no changeset "%s"' % name) + files = sublib.svn_st(files) + if not files: + return Error('no files found') + for file in files: + set = self._files.get(file.abspath(), None) + if set: + set.removeFile(file) + if dest: dest.addFile(file) + self.save() + return Result(0) + + def abandon(self, name): + cs = self.getChangeset(name) + if not cs: + return Error('no changeset "%s"' % name) + #for file in cs._files: + # del self._files[file.abspath()] + del self._sets[name] + self.save() + return Result(0) + + def opened(self, filters=None): + files = sublib.svn_st() + if filters: + fileset = {} + for path_filter in filters: + filtered = filter(path_filter, files) + for file in filtered: + fileset[file.abspath()] = file + files = fileset.values() + default = filter(self._closed, files) + for file in files: + if file in default: + name = 'default' + else: + set = self._files.get(file.abspath(), 0) + if set: + name = set._name + else: + name = '?' + print '%s (%s)' % (file, name) + return Result(0) + + def change(self, name): + cs = self._sets.get(name, None) + if cs: + result = cs.edit() + if result.ok: self.save() + return result + files = sublib.svn_st() + files = filter(self._closed, files) + cs = Changeset(name, files) + result = cs.edit(new=1) + if result.ok: + self._sets[name] = cs + self.save() + return result + + def changes(self, long=False, short=False): + if short: + long = False + pending = '*P*' + submitted = '-S-' + else: + if self._sets: print + pending = '*PENDING*' + submitted = 'SUBMITTED' + sets = self._sets.values() + sets.sort(Changeset.datecmp) + for set in sets: + date = time.strftime('%Y-%M-%d %H:%M', set.localtime()) + name = set.name() + description = set.description() + if set.isPending(): + status = pending + else: + status = submitted + print '%s %s | %-10s' % (date, status, name), + if short: + desc = description[0][:40] + print ': %s' % desc + else: + print '\n ' + '\n '.join(description) + if long: + for file in set.files(): + print ' - %s (%s)' % (file.path, file.mode) + print + return Result(0) + + def describe(self, name): + cs = self.getChangeset(name) + if not cs: + return Error('no changeset "%s"' % name) + return cs.describe() + + def submit(self, name): + cs = self.getChangeset(name) + if not cs: + result = self.create(name) + if not result.ok: return result + cs = result.value + else: + result = self.edit(name) + if not result.ok: return result + result = cs.submit() + if result.ok: + #del self._sets[name] + self.save() + return result + + def review(self, name, + save='', + mail='', + sender='', + interactive=1, + context=32): + cs = self.getChangeset(name) + if not cs: + return Error('no changeset "%s"' % name) + log = ('Code review of changeset %s (created %s)\n\n' + '%s\n' % (cs.name(), cs.date(), '\n'.join(cs.description()))) + zipbuffer = StringIO.StringIO() + zip = zipfile.ZipFile(zipbuffer, 'a') + svn_root = sublib.svn_root() + for file in cs.files(): + path = file.abspath() + exit_code, out = sublib.runo('svn --non-interactive --diff-cmd=/usr/bin/diff' + ' --extensions=-U%d diff %s' % (context, path)) + if exit_code: + return Error('unable to diff %s' % path) + + # replace absolute paths with repository paths + if len(out) >= 4 and out[2].startswith('--- ') and out[3].startswith('+++ '): + file1 = out[2][4:] + if file1.startswith(svn_root): + out[2] = '--- /' + file1[len(svn_root):] + file2 = out[3][4:] + if file2.startswith(svn_root): + out[3] = '+++ /' + file2[len(svn_root):] + + diff = ''.join(out) + log = "%s\n%s" % (log, str(file)) + zip.writestr(file.path + '.diff', diff) + zip.writestr('README.txt', log) + zip.close() + zipdata = zipbuffer.getvalue() + if save: + open(save, 'w').write(zipdata) + result = Result(0) + if mail: + recipients = mail + subject = 'Code review, changeset %s' % name + body = ('%s\n' + '___________________________________________________________________\n' + '\n' + 'The attached zipfile contains diffs of each file in the changeset\n' + 'With a properly configured graphical mail client and diff tool, it\n' + 'should be possible to open the individual file diffs with a few\n' + 'mouse clicks. For assistance, see http://....\n' % log) + if interactive: + print 'edit and save the message to send.' + result = edit(body) + if result.ok: + body = result.value + if not body: return Error('message not saved; aborting.') + result = sendmail(sender, recipients, subject, body, attachments=[(name + '.zip', zipdata)]) + if result.ok: + size = len(zipdata) + len(body) + if size >= 1000000: + size, unit = '%.1f' % (size/1024.0/1024.0), 'M' + elif size >= 10000: + size, unit = '%.0f' % (size/1024.0), 'K' + elif size >= 1000: + size, unit = '%.1f' % (size/1024.0), 'K' + else: + size, unit = '%d' % size, ' bytes' + print 'message sent (%s%s).' % (size, unit) + return result + + def save(self): + if hasattr(self, '_ws'): + self._save() + + +def run(method, *args, **kw): + ws = Workspace() + method = getattr(ws, method) + result = method(*args, **kw) + if result.ok: return 0 + print result.error + return 1 + + +class Command: + Index = {} + + def __init__(self): + self._options = [] + self._keys = [] + self._define() + + def help(self): + self._makeOpt().print_help() + + def _addKeys(self, *keys): + self._keys = keys + for key in keys: + Command.Index[key] = self + + def _addOption(self, *args, **kw): + self._options.append((args, kw)) + + def _makeOpt(self): + opt = optparse.OptionParser(usage=self._long, + add_help_option=0, + formatter=app.CustomUsageFormatter()) + for optargs, optkw in self._options: + opt.add_option(*optargs, **optkw) + return opt + + def _start(self, args): + opt = self._makeOpt() + options, args = opt.parse_args(args) + self._run(options, args) + + def run(command, options): + handler = Command.Index.get(command, None) + if handler is None: + print 'unknown command "%s"' % command + app.usage() + return 1 + return handler._start(options) + run = staticmethod(run) + + +class Opened(Command): + + def _define(self): + self._long = ('opened (o): Show open files.\n' + 'usage: %prog opened [path]') + self._short = 'show opened files' + self._addKeys('opened', 'o') + + def _run(self, options, args): + filters = map(Filter, args) + return run('opened', filters) + + +class Changes(Command): + + def _define(self): + self._long = ('changes: Show all active changesets.\n' + 'usage: %prog changes [options]') + self._short = 'show active changesets' + self._addKeys('changes') + self._addOption('-l', '--long', default=False, action='store_true', help='list full descriptions and changed files') + self._addOption('-s', '--short', default=False, action='store_true', help='list only abbreviated descriptions') + + def _run(self, options, args): + return run('changes', long=options.long, short=options.short) + + +class Assign(Command): + + def _define(self): + self._long = ('assign (a): assign files to an existing changeset, or move files\n' + ' from one changeset to another\n' + 'usage: %prog assign changeset file [file...]\n' + 'If changeset is "default", the files will be removed from all changesets.') + self._short = 'reassign open files to a different changeset' + self._addKeys('assign', 'a') + + def _run(self, options, args): + if len(args) < 2: + self.help() + return 1 + name = args[0] + files = args[1:] + return run('assign', name, files) + + +class Change(Command): + + def _define(self): + self._long = ('change: create or edit a changeset\n' + 'usage: %prog change [options] changeset') + self._short = 'create or edit a changeset' + self._addKeys('change') + self._addOption('-d', '--delete', default=False, action='store_true', help='delete the changeset') + + def _run(self, options, args): + if len(args) != 1: + self.help() + return 1 + name = args[0] + if options.delete: + return run('abandon', name) + else: + return run('change', name) + + +class Review(Command): + + def _define(self): + self._long = ('review: distribute a changeset for review\n' + 'usage: %prog review [options] changeset\n' + '\n' + 'Creates a zipfile containing diffs of all files in the changeset.\n' + 'The zipfile can be saved locally or emailed to reviews along with\n' + 'the changeset description.\n') + self._short = 'submit a changeset for review' + self._addKeys('review') + self._addOption('--context', default='32', metavar='<n>', help='lines of context in diffs') + self._addOption('--from', default='', metavar='<addr>', help='return email address') + self._addOption('--mail', default='', metavar='<addr>', help='recipients (comma separated)') + self._addOption('--noedit', default=False, action='store_true', help='immediate send (no edit)') + self._addOption('--save', default='', metavar='<path>', help='save a copy of the review') + + def _run(self, options, args): + if len(args) != 1: + self.help() + return 1 + name = args[0] + mail = [] + sender = getattr(options, 'from') + if options.mail: + mail = options.mail.split(',') + if not sender: + sender = os.environ.get('SVN_FROM', '') + if not sender: + print 'could not determine your email address; set SVN_FROM or the --from option' + return 1 + try: + context = int(options.context) + except ValueError: + context = 0 + if context < 1: + print 'invalid value (%s) for --context option' % options.context + return 1 + interactive = not options.noedit + save = options.save + return run('review', name, mail=mail, save=save, sender=sender, interactive=interactive, context=context) + + +class Submit(Command): + + def _define(self): + self._long = ('submit: submit (commit) a changeset to the repository\n' + 'usage: %prog submit changeset') + self._short = 'submit a changeset to the repository' + self._addKeys('submit') + + def _run(self, options, args): + if len(args) != 1: + self.help() + return 1 + name = args[0] + return run('submit', name) + + +class Abandon(Command): + + def _define(self): + self._long = ('abandon: discard an existing changeset. open files will be reassigned\n' + 'to the default changeset.\n' + 'usage: %prog abandon changeset') + self._short = 'abandon a changeset' + self._addKeys('abandon') + + def _run(self, options, args): + if len(args) != 1: + self.help() + return 1 + name = args[0] + return run('abandon', name) + + +class Describe(Command): + + def _define(self): + self._long = ('describe (d): show information about a changeset.\n' + 'usage: %prog describe changeset') + self._short = 'describe a changeset' + self._addKeys('describe', 'd') + + def _run(self, options, args): + if len(args) != 1: + self.help() + return 1 + name = args[0] + return run('describe', name) + + +class Help(Command): + + def _define(self): + self._long = ('help (?, h): Describe the usage of this program or its subcommands.\n' + 'usage: %prog help [SUBCOMMAND...]') + self._short = 'describe subcommands' + self._addKeys('help', 'h', '?') + self._addOption('-r') + + def _run(self, options, args): + if len(args) == 1: + key = args[0] + command = Command.Index.get(key, None) + if command is None: + print 'unknown subcommand "%s"' % key + return 1 + command.help() + return 0 + self.help() + return 0 + + def help(self): + print __doc__ % {'prog': app.programName()} + print 'Available commands:' + commands = {} + for command in Command.Index.values(): + primary = command._keys[0] + commands[primary] = command + primaries = commands.keys() + primaries.sort() + for primary in primaries: + command = commands[primary] + aliases = command._keys[1:] + aliases = ', '.join(aliases) + subcommand = primary + if aliases: + subcommand = subcommand + ' (%s)' % aliases + print ' %-20s %s' % (subcommand, command._short) + print + + +# register subcommands +Help(), Opened(), Changes(), Assign(), Describe(), Abandon(), Change(), Submit(), Review() + +def main(args): + if len(args) < 1: + app.usage() + return 0 + command = args[0] + options = args[1:] + return Command.run(command, options) + +app.start(disable_interspersed_args=1) + Property changes on: trunk/CSP/tools/subset ___________________________________________________________________ Name: svn:executable + * |
From: <sv...@ww...> - 2004-05-31 04:10:14
|
Author: wolverine Date: 2004-05-30 21:10:07 -0700 (Sun, 30 May 2004) New Revision: 982 Modified: trunk/CSP/CSPSim/Include/Networking.h Log: added type field to the object update payload Modified: trunk/CSP/CSPSim/Include/Networking.h =================================================================== --- trunk/CSP/CSPSim/Include/Networking.h 2004-05-31 03:32:55 UTC (rev 981) +++ trunk/CSP/CSPSim/Include/Networking.h 2004-05-31 04:10:07 UTC (rev 982) @@ -151,6 +151,7 @@ public: unsigned int id; + unsigned int objectType; simdata::SimTime timeStamp; _Vector3Struct globalPosition; _Vector3Struct linearVelocity; @@ -161,6 +162,7 @@ { simdata::uint32 thisAddr = (simdata::uint32)this; simdata::uint32 idAddr = (simdata::uint32)&id; + simdata::uint32 typeAddr = (simdata::uint32)&objectType; simdata::uint32 timeStampAddr = (simdata::uint32)&timeStamp; simdata::uint32 globalPositionAddr = (simdata::uint32)&globalPosition; simdata::uint32 linearVelocityAddr = (simdata::uint32)&linearVelocity; @@ -168,6 +170,7 @@ simdata::uint32 attitudeAddr = (simdata::uint32)&attitude; printf("ObjectUpdateMessagePayload - IDOffset: %d\n", idAddr - thisAddr ); + printf("ObjectUpdateMessagePayload - TypeOffset: %d\n", typeAddr - thisAddr); printf("ObjectUpdateMessagePayload - timeStampOffset: %d\n", timeStampAddr - thisAddr ); printf("ObjectUpdateMessagePayload - globalPositionOffset: %d\n", globalPositionAddr - thisAddr ); printf("ObjectUpdateMessagePayload - linearVelocityOffset: %d\n", linearVelocityAddr - thisAddr ); |
From: <sv...@ww...> - 2004-05-31 03:33:03
|
Author: wolverine Date: 2004-05-30 20:32:55 -0700 (Sun, 30 May 2004) New Revision: 981 Modified: trunk/CSP/CSPSim/CHANGES.current Log: changed the message sender queue to use a vector that contains a struct with both the destination node along with the message. Modified: trunk/CSP/CSPSim/CHANGES.current =================================================================== --- trunk/CSP/CSPSim/CHANGES.current 2004-05-31 03:29:51 UTC (rev 980) +++ trunk/CSP/CSPSim/CHANGES.current 2004-05-31 03:32:55 UTC (rev 981) @@ -1,6 +1,14 @@ Version 0.4.0 (in progress) =========================== +2004-05-30: wolverine + * 2004-05-30: wolverine + * Changed the router queue in NetworkMessagener to be a vector that + contains a struct with a node and message pointers. This allows + a destination node to be associated with each outgoing message. This + approach hopefully avoids any object creation steps during the queueing + and dequeing processes. + 2004-05-28: wolverine * Created special data transfer structures that contain no virtual functions and have the same fundamental binary structure as SimData types |
From: <sv...@ww...> - 2004-05-31 03:29:58
|
Author: wolverine Date: 2004-05-30 20:29:51 -0700 (Sun, 30 May 2004) New Revision: 980 Modified: trunk/CSP/CSPSim/Source/Networking/NetworkMessenger.cpp Log: changed the message sender queue to use a vector that contains a struct with both the destination node along with the message. Modified: trunk/CSP/CSPSim/Source/Networking/NetworkMessenger.cpp =================================================================== --- trunk/CSP/CSPSim/Source/Networking/NetworkMessenger.cpp 2004-05-31 03:29:39 UTC (rev 979) +++ trunk/CSP/CSPSim/Source/Networking/NetworkMessenger.cpp 2004-05-31 03:29:51 UTC (rev 980) @@ -26,45 +26,49 @@ #include "Log.h" #include "Networking.h" -NetworkNode * g_node; - NetworkMessenger::NetworkMessenger() { m_messageSocketDuplex = new MessageSocketDuplex(); m_orginatorNode = new NetworkNode(); + m_messageArrayMax = 200; + m_messageArrayCount = 0; + m_messageArray.reserve(m_messageArrayMax); } NetworkMessenger::NetworkMessenger(NetworkNode * orginatorNode) { m_messageSocketDuplex = new MessageSocketDuplex(orginatorNode->getPort()); m_orginatorNode = orginatorNode; + m_messageArrayMax = 200; + m_messageArrayCount = 0; + m_messageArray.reserve(m_messageArrayMax); } void NetworkMessenger::queueMessage(NetworkNode * node, NetworkMessage * message) { CSP_LOG(APP, DEBUG, "NetworkMessenger::queueMessage()"); - m_messageList.push_back(message); - g_node = node; + if (m_messageArrayCount >= m_messageArrayMax) + { + m_messageArrayMax += m_messageArrayGrow; + m_messageArray.resize(m_messageArrayMax); + } + m_messageArray[m_messageArrayCount].m_destinationNode = node; + m_messageArray[m_messageArrayCount].m_message = message; + m_messageArrayCount++; } void NetworkMessenger::sendMessages() { CSP_LOG(APP, DEBUG, "NetworkMessenger::sendMessages()"); - while(!m_messageList.empty()) - { - NetworkMessage * message = m_messageList.front(); - m_messageSocketDuplex->sendto(message, g_node); - m_messageList.pop_front(); - returnMessageToPool(message); - - } -// std::list<NetworkMessage*>::iterator i = m_messageList.begin(); -// std::list<NetworkMessage*>::const_iterator end = m_messageList.end(); -// for ( ; i != end ; ++i ) -// { -// m_messageSocketDuplex->sendto((*i), g_node); -// } - + + for(int i=0;i<m_messageArrayCount;i++) { + m_messageSocketDuplex->sendto(m_messageArray[i].m_message, + m_messageArray[i].m_destinationNode); + returnMessageToPool(m_messageArray[i].m_message); + m_messageArray[i].m_message = NULL; + } + m_messageArrayCount = 0; + } void NetworkMessenger::receiveMessages() @@ -100,7 +104,7 @@ } NetworkMessage * message = m_messagePool.front(); m_messagePool.pop_front(); - memset(message, 0x00, 512); + memset(message, 0x00, NETWORK_PACKET_SIZE); message->initialize( messageType, payloadLen, m_orginatorNode); return message; } |
From: <sv...@ww...> - 2004-05-31 03:29:45
|
Author: wolverine Date: 2004-05-30 20:29:39 -0700 (Sun, 30 May 2004) New Revision: 979 Modified: trunk/CSP/CSPSim/Include/Networking.h Log: changed the message sender queue to use a vector that contains a struct with both the destination node along with the message. Modified: trunk/CSP/CSPSim/Include/Networking.h =================================================================== --- trunk/CSP/CSPSim/Include/Networking.h 2004-05-30 23:43:44 UTC (rev 978) +++ trunk/CSP/CSPSim/Include/Networking.h 2004-05-31 03:29:39 UTC (rev 979) @@ -237,11 +237,20 @@ }; +struct MessageRoute +{ + NetworkNode * m_destinationNode; + NetworkMessage * m_message; +}; + class NetworkMessenger { private: MessageSocketDuplex * m_messageSocketDuplex; - std::list<NetworkMessage*> m_messageList; + std::vector<MessageRoute> m_messageArray; + int m_messageArrayMax; + int m_messageArrayCount; + int m_messageArrayGrow; NetworkNode * m_orginatorNode; std::list<NetworkMessage*> m_messagePool; |
From: <sv...@ww...> - 2004-05-30 23:43:51
|
Author: wolverine Date: 2004-05-30 16:43:44 -0700 (Sun, 30 May 2004) New Revision: 978 Modified: trunk/CSP/CSPSim/Source/ServerNode.cpp Log: changes output for timestamp to use float Modified: trunk/CSP/CSPSim/Source/ServerNode.cpp =================================================================== --- trunk/CSP/CSPSim/Source/ServerNode.cpp 2004-05-29 21:43:33 UTC (rev 977) +++ trunk/CSP/CSPSim/Source/ServerNode.cpp 2004-05-30 23:43:44 UTC (rev 978) @@ -51,7 +51,7 @@ ObjectUpdateMessagePayload * ptrPayload = (ObjectUpdateMessagePayload*)message->getPayloadPtr(); ptrPayload->dumpOffsets(); printf("ID: %u\n", ptrPayload->id); - printf("TimeStamp: %u\n", ptrPayload->timeStamp); + printf("TimeStamp: %f\n", ptrPayload->timeStamp); printf("PositionX: %f, PositionY: %f, PositionZ: %f\n", ptrPayload->globalPosition.x, ptrPayload->globalPosition.y, |
From: <sv...@ww...> - 2004-05-29 21:43:39
|
Author: wolverine Date: 2004-05-29 14:43:33 -0700 (Sat, 29 May 2004) New Revision: 977 Modified: trunk/CSP/CSPSim/Include/Networking.h Log: Using same packing on both linux and windows Modified: trunk/CSP/CSPSim/Include/Networking.h =================================================================== --- trunk/CSP/CSPSim/Include/Networking.h 2004-05-29 21:42:38 UTC (rev 976) +++ trunk/CSP/CSPSim/Include/Networking.h 2004-05-29 21:43:33 UTC (rev 977) @@ -47,10 +47,9 @@ const short NETWORK_PACKET_SIZE = 512; -#ifdef WIN32 -#pragma pack(push) -#pragma pack(1) -#endif +//#ifdef WIN32 +#pragma pack(push, 1) +//#endif // Define some structs that will only used for data transfers. @@ -178,9 +177,9 @@ }; -#ifdef WIN32 +//#ifdef WIN32 #pragma pack(pop) -#endif +//#endif class NetworkMessagePool { |
From: <sv...@ww...> - 2004-05-29 21:42:44
|
Author: wolverine Date: 2004-05-29 14:42:38 -0700 (Sat, 29 May 2004) New Revision: 976 Modified: trunk/CSP/CSPSim/Source/Networking/NetworkMessenger.cpp Log: commented out print statements Modified: trunk/CSP/CSPSim/Source/Networking/NetworkMessenger.cpp =================================================================== --- trunk/CSP/CSPSim/Source/Networking/NetworkMessenger.cpp 2004-05-29 20:13:04 UTC (rev 975) +++ trunk/CSP/CSPSim/Source/Networking/NetworkMessenger.cpp 2004-05-29 21:42:38 UTC (rev 976) @@ -88,7 +88,7 @@ // buffer then cast it to a NetworkMessage pointer. NetworkMessage * NetworkMessenger::getMessageFromPool(int messageType, int payloadLen) { - printf("NetworkMessenger::getMessageFromPool() - CurrentPoolSize: %d\n", m_messagePool.size()); + //printf("NetworkMessenger::getMessageFromPool() - CurrentPoolSize: %d\n", m_messagePool.size()); if (m_messagePool.empty()) { for(int i=0;i<100;i++) @@ -108,7 +108,7 @@ // cast the NetworkMessage pointer back to a binary buffer then free the buffer. void NetworkMessenger::returnMessageToPool(NetworkMessage * message) { - printf("NetworkMessenger::returnMessageToPool() - CurrentPoolSize: %d\n", m_messagePool.size()); +// printf("NetworkMessenger::returnMessageToPool() - CurrentPoolSize: %d\n", m_messagePool.size()); m_messagePool.push_back(message); } |
From: <sv...@ww...> - 2004-05-29 20:13:10
|
Author: wolverine Date: 2004-05-29 13:13:04 -0700 (Sat, 29 May 2004) New Revision: 975 Modified: trunk/CSP/CSPSim/Include/Networking.h Log: added packing to the network structures. Modified: trunk/CSP/CSPSim/Include/Networking.h =================================================================== --- trunk/CSP/CSPSim/Include/Networking.h 2004-05-29 18:59:11 UTC (rev 974) +++ trunk/CSP/CSPSim/Include/Networking.h 2004-05-29 20:13:04 UTC (rev 975) @@ -47,6 +47,32 @@ const short NETWORK_PACKET_SIZE = 512; +#ifdef WIN32 +#pragma pack(push) +#pragma pack(1) +#endif + + +// Define some structs that will only used for data transfers. +// These differ from SimData structs in that they have no virtual +// functions and hence have more predictable binary sizes. +struct _Vector3Struct +{ + double x; + double y; + double z; +}; + +struct _QuatStruct +{ + double x; + double y; + double z; + double w; +}; + + + struct MessageHeader { simdata::uint16 m_magicNumber; @@ -118,33 +144,9 @@ }; -class NetworkMessagePool +struct ObjectUpdateMessagePayload { - -}; - -// Define some structs that will only used for data transfers. -// These differ from SimData structs in that they have no virtual -// functions and hence have more predictable binary sizes. -struct _Vector3Struct -{ - double x; - double y; - double z; -}; - -struct _QuatStruct -{ - double x; - double y; - double z; - double w; -}; - -class ObjectUpdateMessagePayload -{ - private: ObjectUpdateMessagePayload(); @@ -176,7 +178,17 @@ }; +#ifdef WIN32 +#pragma pack(pop) +#endif +class NetworkMessagePool +{ + + +}; + + class NetworkNode { private: |
From: <sv...@ww...> - 2004-05-29 18:59:17
|
Author: wolverine Date: 2004-05-29 11:59:11 -0700 (Sat, 29 May 2004) New Revision: 974 Modified: trunk/CSP/CSPSim/Source/ClientNode.cpp trunk/CSP/CSPSim/Source/ServerNode.cpp Log: added a dumpOffsets routine to the objectUpdate Payload Modified: trunk/CSP/CSPSim/Source/ClientNode.cpp =================================================================== --- trunk/CSP/CSPSim/Source/ClientNode.cpp 2004-05-29 18:58:50 UTC (rev 973) +++ trunk/CSP/CSPSim/Source/ClientNode.cpp 2004-05-29 18:59:11 UTC (rev 974) @@ -62,7 +62,7 @@ NetworkMessage * message = networkMessenger->getMessageFromPool(messageType, payloadLen); ObjectUpdateMessagePayload * ptrPayload = (ObjectUpdateMessagePayload*)message->getPayloadPtr(); - + ptrPayload->dumpOffsets(); // NetworkMessage * message = networkMessenger->getMessageFromPool(1, 100); // memset(payloadPtr, 0 , 100); Modified: trunk/CSP/CSPSim/Source/ServerNode.cpp =================================================================== --- trunk/CSP/CSPSim/Source/ServerNode.cpp 2004-05-29 18:58:50 UTC (rev 973) +++ trunk/CSP/CSPSim/Source/ServerNode.cpp 2004-05-29 18:59:11 UTC (rev 974) @@ -36,7 +36,8 @@ { NetworkNode * node = message->getOriginatorNode(); MessageHeader * header = (MessageHeader*)message; - printf("Received Data From Client:\n"); + header->dumpOffsets(); + printf("Received Data From Client:\n"); printf("Client addr: %s\n", node->getHostname()); printf("Client port: %d\n", node->getPort()); @@ -47,8 +48,9 @@ printf("Port: %u\n", header->m_port); printf("ID: %u\n", header->m_id); - ObjectUpdateMessagePayload * ptrPayload = (ObjectUpdateMessagePayload*)message->getPayloadPtr(); - printf("ID: %u\n", ptrPayload->id); + ObjectUpdateMessagePayload * ptrPayload = (ObjectUpdateMessagePayload*)message->getPayloadPtr(); + ptrPayload->dumpOffsets(); + printf("ID: %u\n", ptrPayload->id); printf("TimeStamp: %u\n", ptrPayload->timeStamp); printf("PositionX: %f, PositionY: %f, PositionZ: %f\n", ptrPayload->globalPosition.x, |
From: <sv...@ww...> - 2004-05-29 18:59:00
|
Author: wolverine Date: 2004-05-29 11:58:50 -0700 (Sat, 29 May 2004) New Revision: 973 Modified: trunk/CSP/CSPSim/Include/Networking.h Log: added a dumpOffsets routine to the objectUpdate Payload Modified: trunk/CSP/CSPSim/Include/Networking.h =================================================================== --- trunk/CSP/CSPSim/Include/Networking.h 2004-05-29 16:00:10 UTC (rev 972) +++ trunk/CSP/CSPSim/Include/Networking.h 2004-05-29 18:58:50 UTC (rev 973) @@ -156,6 +156,23 @@ _Vector3Struct angularVelocity; _QuatStruct attitude; + void dumpOffsets() + { + simdata::uint32 thisAddr = (simdata::uint32)this; + simdata::uint32 idAddr = (simdata::uint32)&id; + simdata::uint32 timeStampAddr = (simdata::uint32)&timeStamp; + simdata::uint32 globalPositionAddr = (simdata::uint32)&globalPosition; + simdata::uint32 linearVelocityAddr = (simdata::uint32)&linearVelocity; + simdata::uint32 angularVelocityAddr = (simdata::uint32)&angularVelocity; + simdata::uint32 attitudeAddr = (simdata::uint32)&attitude; + + printf("ObjectUpdateMessagePayload - IDOffset: %d\n", idAddr - thisAddr ); + printf("ObjectUpdateMessagePayload - timeStampOffset: %d\n", timeStampAddr - thisAddr ); + printf("ObjectUpdateMessagePayload - globalPositionOffset: %d\n", globalPositionAddr - thisAddr ); + printf("ObjectUpdateMessagePayload - linearVelocityOffset: %d\n", linearVelocityAddr - thisAddr ); + printf("ObjectUpdateMessagePayload - angularVelocityOffset: %d\n", angularVelocityAddr - thisAddr ); + printf("ObjectUpdateMessagePayload - attitudeOffset: %d\n", attitudeAddr - thisAddr ); + } }; |