Skip to content

Instantly share code, notes, and snippets.

@p
Created June 17, 2010 21:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save p/442828 to your computer and use it in GitHub Desktop.
Save p/442828 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# Synchronizes an upstream package to a new version of itself.
# Removes files/dirs in our version no longer present in the new version,
# and adds files/dirs from new version that are not in our version.
#
# Sample usage: sync-upstream current new
import re, os, os.path, shutil, subprocess, sys
if len(sys.argv) != 3:
print >>sys.stderr, "Usage: sync-upstream current new"
exit(2)
base = sys.argv[1]
if not base.endswith('/'):
base += '/'
new = sys.argv[2]
if not new.endswith('/'):
new += '/'
base_re = re.compile('^'+re.escape(base))
new_re = re.compile('^'+re.escape(new))
def execute(cmd, *args):
subprocess.check_call([cmd] + list(args))
def prune(what):
if what not in ['files', 'dirs']:
raise ValueError, "what must be files or dirs"
if what == 'files':
test = 'isfile'
else:
test = 'isdir'
paths_to_remove = []
for root_in_base, dirs, files in os.walk(base):
if '.svn' in dirs:
dirs.remove('.svn')
root_in_new = base_re.sub(new, root_in_base)
if what == 'files':
targets = files
else:
targets = dirs
for file in targets:
path_in_new = os.path.join(root_in_new, file)
if not getattr(os.path, test)(path_in_new):
paths_to_remove.append(os.path.join(root_in_base, file))
if len(paths_to_remove) > 0:
execute('svn', 'rm', *paths_to_remove)
def add(what):
if what not in ['files', 'dirs']:
raise ValueError, "what must be files or dirs"
if what == 'files':
test = 'isfile'
else:
test = 'isdir'
paths_to_add = []
for root_in_new, dirs, files in os.walk(new):
root_in_base = new_re.sub(base, root_in_new)
if what == 'files':
targets = files
else:
targets = dirs
for file in targets:
path_in_base = os.path.join(root_in_base, file)
if not getattr(os.path, test)(path_in_base):
if what == 'files':
shutil.copy2(os.path.join(root_in_new, file), path_in_base)
else:
os.mkdir(path_in_base)
paths_to_add.append(path_in_base)
if len(paths_to_add) > 0:
execute('svn', 'add', *paths_to_add)
def copy():
for root_in_new, dirs, files in os.walk(new):
root_in_base = new_re.sub(base, root_in_new)
for file in files:
path_in_base = os.path.join(root_in_base, file)
shutil.copy2(os.path.join(root_in_new, file), path_in_base)
prune('files')
prune('dirs')
add('dirs')
add('files')
copy()
# Copyright (C) 2010 Oleg Pudeyev
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment