git_remote_helpers: add fastimport library
[git/dscho.git] / git_remote_helpers / fastimport / helpers.py
blob3ce5a98e1722c722ee391c5cc969ff7d2d138a29
1 # Copyright (C) 2008 Canonical Ltd
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 """Miscellaneous useful stuff."""
19 import os
21 def single_plural(n, single, plural):
22 """Return a single or plural form of a noun based on number."""
23 if n == 1:
24 return single
25 else:
26 return plural
29 def invert_dict(d):
30 """Invert a dictionary with keys matching each value turned into a list."""
31 # Based on recipe from ASPN
32 result = {}
33 for k, v in d.iteritems():
34 keys = result.setdefault(v, [])
35 keys.append(k)
36 return result
39 def invert_dictset(d):
40 """Invert a dictionary with keys matching a set of values, turned into lists."""
41 # Based on recipe from ASPN
42 result = {}
43 for k, c in d.iteritems():
44 for v in c:
45 keys = result.setdefault(v, [])
46 keys.append(k)
47 return result
50 def _common_path_and_rest(l1, l2, common=[]):
51 # From http://code.activestate.com/recipes/208993/
52 if len(l1) < 1: return (common, l1, l2)
53 if len(l2) < 1: return (common, l1, l2)
54 if l1[0] != l2[0]: return (common, l1, l2)
55 return _common_path_and_rest(l1[1:], l2[1:], common+[l1[0]])
58 def common_path(path1, path2):
59 """Find the common bit of 2 paths."""
60 return ''.join(_common_path_and_rest(path1, path2)[0])
63 def common_directory(paths):
64 """Find the deepest common directory of a list of paths.
66 :return: if no paths are provided, None is returned;
67 if there is no common directory, '' is returned;
68 otherwise the common directory with a trailing / is returned.
69 """
70 def get_dir_with_slash(path):
71 if path == '' or path.endswith('/'):
72 return path
73 else:
74 dirname, basename = os.path.split(path)
75 if dirname == '':
76 return dirname
77 else:
78 return dirname + '/'
80 if not paths:
81 return None
82 elif len(paths) == 1:
83 return get_dir_with_slash(paths[0])
84 else:
85 common = common_path(paths[0], paths[1])
86 for path in paths[2:]:
87 common = common_path(common, path)
88 return get_dir_with_slash(common)