Browse code

* s3cmd: Implemented --include and friends.

git-svn-id: https://s3tools.svn.sourceforge.net/svnroot/s3tools/s3cmd/trunk@357 830e0280-6d2a-0410-9c65-932aecc39d9d

W. Tell authored on 2009/01/25 19:47:49
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+2009-01-25  W. Tell  <w_tell -at- sourceforge>
2
+
3
+	* s3cmd: Implemented --include and friends.
4
+
1 5
 2009-01-25  Michal Ludvig  <michal@logix.cz>
2 6
 
3 7
 	* s3cmd: Enabled --dry-run and --exclude for 'put' and 'get'.
... ...
@@ -1185,18 +1185,50 @@ def run_configure(config_file):
1185 1185
 		error(u"Writing config file failed: %s: %s" % (config_file, e.strerror))
1186 1186
 		sys.exit(1)
1187 1187
 
1188
-def process_exclude_from_file(exf, exclude_array):
1188
+def process_patterns_from_file(fname, patterns_list):
1189 1189
 	try:
1190
-		exfi = open(exf, "rt")
1190
+		fn = open(fname, "rt")
1191 1191
 	except IOError, e:
1192 1192
 		error(e)
1193 1193
 		sys.exit(1)
1194
-	for ex in exfi:
1195
-		ex = ex.strip()
1196
-		if re.match("^#", ex) or re.match("^\s*$", ex):
1194
+	for pattern in fn:
1195
+		pattern = pattern.strip()
1196
+		if re.match("^#", pattern) or re.match("^\s*$", pattern):
1197 1197
 			continue
1198
-		debug(u"adding rule: %s" % ex)
1199
-		exclude_array.append(ex)
1198
+		debug(u"%s: adding rule: %s" % (fname, pattern))
1199
+		patterns_list.append(pattern)
1200
+
1201
+	return patterns_list
1202
+
1203
+def process_patterns(patterns_list, patterns_from, is_glob, option_txt = ""):
1204
+	"""
1205
+	process_patterns(patterns, patterns_from, is_glob, option_txt = "")
1206
+	Process --exclude / --include GLOB and REGEXP patterns.
1207
+	'option_txt' is 'exclude' / 'include' / 'rexclude' / 'rinclude'
1208
+	Returns: patterns_compiled, patterns_text
1209
+	"""
1210
+
1211
+	patterns_compiled = []
1212
+	patterns_textual = {}
1213
+
1214
+	if patterns_list is None:
1215
+		patterns_list = []
1216
+
1217
+	if patterns_from:
1218
+		## Append patterns from glob_from 
1219
+		for fname in patterns_from:
1220
+			debug(u"processing --%s-from %s" % (option_txt, fname))
1221
+			patterns_list = process_patterns_from_file(fname, patterns_list)
1222
+
1223
+	for pattern in patterns_list:
1224
+		debug(u"processing %s rule: %s" % (option_txt, patterns_list))
1225
+		if is_glob:
1226
+			pattern = glob.fnmatch.translate(pattern)
1227
+		r = re.compile(pattern)
1228
+		patterns_compiled.append(r)
1229
+		patterns_textual[r] = pattern
1230
+
1231
+	return patterns_compiled, patterns_textual
1200 1232
 
1201 1233
 commands = {}
1202 1234
 commands_list = [
... ...
@@ -1288,6 +1320,10 @@ def main():
1288 1288
 	optparser.add_option(      "--exclude-from", dest="exclude_from", action="append", metavar="FILE", help="Read --exclude GLOBs from FILE")
1289 1289
 	optparser.add_option(      "--rexclude", dest="rexclude", action="append", metavar="REGEXP", help="Filenames and paths matching REGEXP (regular expression) will be excluded from sync")
1290 1290
 	optparser.add_option(      "--rexclude-from", dest="rexclude_from", action="append", metavar="FILE", help="Read --rexclude REGEXPs from FILE")
1291
+	optparser.add_option(      "--include", dest="include", action="append", metavar="GLOB", help="Filenames and paths matching GLOB will be included even if previously excluded by one of --(r)exclude(-from) patterns")
1292
+	optparser.add_option(      "--include-from", dest="include_from", action="append", metavar="FILE", help="Read --include GLOBs from FILE")
1293
+	optparser.add_option(      "--rinclude", dest="rinclude", action="append", metavar="REGEXP", help="Same as --include but uses REGEXP (regular expression) instead of GLOB")
1294
+	optparser.add_option(      "--rinclude-from", dest="rinclude_from", action="append", metavar="FILE", help="Read --rinclude REGEXPs from FILE")
1291 1295
 	optparser.add_option(      "--debug-syncmatch", "--debug-exclude", dest="debug_syncmatch", action="store_true", help="Output detailed information about remote vs. local filelist matching and --exclude processing and then exit")
1292 1296
 
1293 1297
 	optparser.add_option(      "--bucket-location", dest="bucket_location", help="Datacentre to create bucket in. Either EU or US (default)")
... ...
@@ -1374,37 +1410,25 @@ def main():
1374 1374
 	sys.stdout = codecs.getwriter(cfg.encoding)(sys.stdout, "replace")
1375 1375
 	sys.stderr = codecs.getwriter(cfg.encoding)(sys.stderr, "replace")
1376 1376
 
1377
-	## Process GLOB (shell wildcard style) excludes
1378
-	if options.exclude is None:
1379
-		options.exclude = []
1380
-
1381
-	if options.exclude_from:
1382
-		for exf in options.exclude_from:
1383
-			debug(u"processing --exclude-from %s" % exf)
1384
-			process_exclude_from_file(exf, options.exclude)
1385
-
1386
-	if options.exclude:
1387
-		for ex in options.exclude:
1388
-			debug(u"processing rule: %s" % ex)
1389
-			exc = re.compile(glob.fnmatch.translate(ex))
1390
-			cfg.exclude.append(exc)
1391
-			cfg.debug_exclude[exc] = ex
1392
-
1393
-	## Process REGEXP style excludes
1394
-	if options.rexclude is None:
1395
-		options.rexclude = []
1396
-
1397
-	if options.rexclude_from:
1398
-		for exf in options.rexclude_from:
1399
-			debug(u"processing --rexclude-from %s" % exf)
1400
-			process_exclude_from_file(exf, options.rexclude)
1401
-
1402
-	if options.rexclude:
1403
-		for ex in options.rexclude:
1404
-			debug(u"processing rule: %s" % ex)
1405
-			exc = re.compile(ex)
1406
-			cfg.exclude.append(exc)
1407
-			cfg.debug_exclude[exc] = ex
1377
+	## Process --exclude and --exclude-from
1378
+	patterns_list, patterns_textual = process_patterns(options.exclude, options.exclude_from, is_glob = True, option_txt = "exclude")
1379
+	cfg.exclude.extend(patterns_list)
1380
+	cfg.debug_exclude.update(patterns_textual)
1381
+
1382
+	## Process --rexclude and --rexclude-from
1383
+	patterns_list, patterns_textual = process_patterns(options.rexclude, options.rexclude_from, is_glob = False, option_txt = "rexclude")
1384
+	cfg.exclude.extend(patterns_list)
1385
+	cfg.debug_exclude.update(patterns_textual)
1386
+
1387
+	## Process --include and --include-from
1388
+	patterns_list, patterns_textual = process_patterns(options.include, options.include_from, is_glob = True, option_txt = "include")
1389
+	cfg.include.extend(patterns_list)
1390
+	cfg.debug_include.update(patterns_textual)
1391
+
1392
+	## Process --rinclude and --rinclude-from
1393
+	patterns_list, patterns_textual = process_patterns(options.rinclude, options.rinclude_from, is_glob = False, option_txt = "rinclude")
1394
+	cfg.include.extend(patterns_list)
1395
+	cfg.debug_include.update(patterns_textual)
1408 1396
 
1409 1397
 	if cfg.encrypt and cfg.gpg_passphrase == "":
1410 1398
 		error(u"Encryption requested but no passphrase set in config file.")