Show More
@@ -0,0 +1,48 b'' | |||||
|
1 | # sparse.py - functionality for sparse checkouts | |||
|
2 | # | |||
|
3 | # Copyright 2014 Facebook, Inc. | |||
|
4 | # | |||
|
5 | # This software may be used and distributed according to the terms of the | |||
|
6 | # GNU General Public License version 2 or any later version. | |||
|
7 | ||||
|
8 | from __future__ import absolute_import | |||
|
9 | ||||
|
10 | from .i18n import _ | |||
|
11 | from . import ( | |||
|
12 | error, | |||
|
13 | ) | |||
|
14 | ||||
|
15 | def parseconfig(ui, raw): | |||
|
16 | """Parse sparse config file content. | |||
|
17 | ||||
|
18 | Returns a tuple of includes, excludes, and profiles. | |||
|
19 | """ | |||
|
20 | includes = set() | |||
|
21 | excludes = set() | |||
|
22 | current = includes | |||
|
23 | profiles = [] | |||
|
24 | for line in raw.split('\n'): | |||
|
25 | line = line.strip() | |||
|
26 | if not line or line.startswith('#'): | |||
|
27 | # empty or comment line, skip | |||
|
28 | continue | |||
|
29 | elif line.startswith('%include '): | |||
|
30 | line = line[9:].strip() | |||
|
31 | if line: | |||
|
32 | profiles.append(line) | |||
|
33 | elif line == '[include]': | |||
|
34 | if current != includes: | |||
|
35 | # TODO pass filename into this API so we can report it. | |||
|
36 | raise error.Abort(_('sparse config cannot have includes ' + | |||
|
37 | 'after excludes')) | |||
|
38 | continue | |||
|
39 | elif line == '[exclude]': | |||
|
40 | current = excludes | |||
|
41 | elif line: | |||
|
42 | if line.strip().startswith('/'): | |||
|
43 | ui.warn(_('warning: sparse profile cannot use' + | |||
|
44 | ' paths starting with /, ignoring %s\n') % line) | |||
|
45 | continue | |||
|
46 | current.add(line) | |||
|
47 | ||||
|
48 | return includes, excludes, profiles |
@@ -92,6 +92,7 b' from mercurial import (' | |||||
92 | match as matchmod, |
|
92 | match as matchmod, | |
93 | merge as mergemod, |
|
93 | merge as mergemod, | |
94 | registrar, |
|
94 | registrar, | |
|
95 | sparse, | |||
95 | util, |
|
96 | util, | |
96 | ) |
|
97 | ) | |
97 |
|
98 | |||
@@ -407,40 +408,6 b' def _setupdirstate(ui):' | |||||
407 |
|
408 | |||
408 | def _wraprepo(ui, repo): |
|
409 | def _wraprepo(ui, repo): | |
409 | class SparseRepo(repo.__class__): |
|
410 | class SparseRepo(repo.__class__): | |
410 | def readsparseconfig(self, raw): |
|
|||
411 | """Takes a string sparse config and returns the includes, |
|
|||
412 | excludes, and profiles it specified. |
|
|||
413 | """ |
|
|||
414 | includes = set() |
|
|||
415 | excludes = set() |
|
|||
416 | current = includes |
|
|||
417 | profiles = [] |
|
|||
418 | for line in raw.split('\n'): |
|
|||
419 | line = line.strip() |
|
|||
420 | if not line or line.startswith('#'): |
|
|||
421 | # empty or comment line, skip |
|
|||
422 | continue |
|
|||
423 | elif line.startswith('%include '): |
|
|||
424 | line = line[9:].strip() |
|
|||
425 | if line: |
|
|||
426 | profiles.append(line) |
|
|||
427 | elif line == '[include]': |
|
|||
428 | if current != includes: |
|
|||
429 | raise error.Abort(_('.hg/sparse cannot have includes ' + |
|
|||
430 | 'after excludes')) |
|
|||
431 | continue |
|
|||
432 | elif line == '[exclude]': |
|
|||
433 | current = excludes |
|
|||
434 | elif line: |
|
|||
435 | if line.strip().startswith('/'): |
|
|||
436 | self.ui.warn(_('warning: sparse profile cannot use' + |
|
|||
437 | ' paths starting with /, ignoring %s\n') |
|
|||
438 | % line) |
|
|||
439 | continue |
|
|||
440 | current.add(line) |
|
|||
441 |
|
||||
442 | return includes, excludes, profiles |
|
|||
443 |
|
||||
444 | def getsparsepatterns(self, rev): |
|
411 | def getsparsepatterns(self, rev): | |
445 | """Returns the include/exclude patterns specified by the |
|
412 | """Returns the include/exclude patterns specified by the | |
446 | given rev. |
|
413 | given rev. | |
@@ -452,7 +419,7 b' def _wraprepo(ui, repo):' | |||||
452 | raise error.Abort(_("cannot parse sparse patterns from " + |
|
419 | raise error.Abort(_("cannot parse sparse patterns from " + | |
453 | "working copy")) |
|
420 | "working copy")) | |
454 |
|
421 | |||
455 |
includes, excludes, profiles = self. |
|
422 | includes, excludes, profiles = sparse.parseconfig(self.ui, raw) | |
456 |
|
423 | |||
457 | ctx = self[rev] |
|
424 | ctx = self[rev] | |
458 | if profiles: |
|
425 | if profiles: | |
@@ -475,8 +442,8 b' def _wraprepo(ui, repo):' | |||||
475 | else: |
|
442 | else: | |
476 | self.ui.debug(msg) |
|
443 | self.ui.debug(msg) | |
477 | continue |
|
444 | continue | |
478 |
pincludes, pexcludes, subprofs = |
|
445 | pincludes, pexcludes, subprofs = sparse.parseconfig( | |
479 |
self. |
|
446 | self.ui, raw) | |
480 | includes.update(pincludes) |
|
447 | includes.update(pincludes) | |
481 | excludes.update(pexcludes) |
|
448 | excludes.update(pexcludes) | |
482 | for subprofile in subprofs: |
|
449 | for subprofile in subprofs: | |
@@ -787,7 +754,7 b' def _config(ui, repo, pats, opts, includ' | |||||
787 | raw = repo.vfs.tryread('sparse') |
|
754 | raw = repo.vfs.tryread('sparse') | |
788 | if raw: |
|
755 | if raw: | |
789 | oldinclude, oldexclude, oldprofiles = map( |
|
756 | oldinclude, oldexclude, oldprofiles = map( | |
790 |
set, re |
|
757 | set, sparse.parseconfig(ui, raw)) | |
791 | else: |
|
758 | else: | |
792 | oldinclude = set() |
|
759 | oldinclude = set() | |
793 | oldexclude = set() |
|
760 | oldexclude = set() | |
@@ -846,7 +813,7 b' def _import(ui, repo, files, opts, force' | |||||
846 |
|
813 | |||
847 | # read current configuration |
|
814 | # read current configuration | |
848 | raw = repo.vfs.tryread('sparse') |
|
815 | raw = repo.vfs.tryread('sparse') | |
849 |
oincludes, oexcludes, oprofiles = re |
|
816 | oincludes, oexcludes, oprofiles = sparse.parseconfig(ui, raw) | |
850 | includes, excludes, profiles = map( |
|
817 | includes, excludes, profiles = map( | |
851 | set, (oincludes, oexcludes, oprofiles)) |
|
818 | set, (oincludes, oexcludes, oprofiles)) | |
852 |
|
819 | |||
@@ -863,8 +830,8 b' def _import(ui, repo, files, opts, force' | |||||
863 | changed = False |
|
830 | changed = False | |
864 | for file in files: |
|
831 | for file in files: | |
865 | with util.posixfile(util.expandpath(file)) as importfile: |
|
832 | with util.posixfile(util.expandpath(file)) as importfile: | |
866 |
iincludes, iexcludes, iprofiles = re |
|
833 | iincludes, iexcludes, iprofiles = sparse.parseconfig( | |
867 | importfile.read()) |
|
834 | ui, importfile.read()) | |
868 | oldsize = len(includes) + len(excludes) + len(profiles) |
|
835 | oldsize = len(includes) + len(excludes) + len(profiles) | |
869 | includes.update(iincludes - aincludes) |
|
836 | includes.update(iincludes - aincludes) | |
870 | excludes.update(iexcludes - aexcludes) |
|
837 | excludes.update(iexcludes - aexcludes) | |
@@ -897,7 +864,7 b' def _import(ui, repo, files, opts, force' | |||||
897 | def _clear(ui, repo, files, force=False): |
|
864 | def _clear(ui, repo, files, force=False): | |
898 | with repo.wlock(): |
|
865 | with repo.wlock(): | |
899 | raw = repo.vfs.tryread('sparse') |
|
866 | raw = repo.vfs.tryread('sparse') | |
900 |
includes, excludes, profiles = re |
|
867 | includes, excludes, profiles = sparse.parseconfig(ui, raw) | |
901 |
|
868 | |||
902 | if includes or excludes: |
|
869 | if includes or excludes: | |
903 | oldstatus = repo.status() |
|
870 | oldstatus = repo.status() |
General Comments 0
You need to be logged in to leave comments.
Login now