1865 Returns 0 on success, 1 if errors are encountered. |
1863 Returns 0 on success, 1 if errors are encountered. |
1866 """ |
1864 """ |
1867 with repo.wlock(False): |
1865 with repo.wlock(False): |
1868 return cmdutil.copy(ui, repo, pats, opts) |
1866 return cmdutil.copy(ui, repo, pats, opts) |
1869 |
1867 |
1870 @command('debugbuilddag', |
|
1871 [('m', 'mergeable-file', None, _('add single file mergeable changes')), |
|
1872 ('o', 'overwritten-file', None, _('add single file all revs overwrite')), |
|
1873 ('n', 'new-file', None, _('add new file at each rev'))], |
|
1874 _('[OPTION]... [TEXT]')) |
|
1875 def debugbuilddag(ui, repo, text=None, |
|
1876 mergeable_file=False, |
|
1877 overwritten_file=False, |
|
1878 new_file=False): |
|
1879 """builds a repo with a given DAG from scratch in the current empty repo |
|
1880 |
|
1881 The description of the DAG is read from stdin if not given on the |
|
1882 command line. |
|
1883 |
|
1884 Elements: |
|
1885 |
|
1886 - "+n" is a linear run of n nodes based on the current default parent |
|
1887 - "." is a single node based on the current default parent |
|
1888 - "$" resets the default parent to null (implied at the start); |
|
1889 otherwise the default parent is always the last node created |
|
1890 - "<p" sets the default parent to the backref p |
|
1891 - "*p" is a fork at parent p, which is a backref |
|
1892 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs |
|
1893 - "/p2" is a merge of the preceding node and p2 |
|
1894 - ":tag" defines a local tag for the preceding node |
|
1895 - "@branch" sets the named branch for subsequent nodes |
|
1896 - "#...\\n" is a comment up to the end of the line |
|
1897 |
|
1898 Whitespace between the above elements is ignored. |
|
1899 |
|
1900 A backref is either |
|
1901 |
|
1902 - a number n, which references the node curr-n, where curr is the current |
|
1903 node, or |
|
1904 - the name of a local tag you placed earlier using ":tag", or |
|
1905 - empty to denote the default parent. |
|
1906 |
|
1907 All string valued-elements are either strictly alphanumeric, or must |
|
1908 be enclosed in double quotes ("..."), with "\\" as escape character. |
|
1909 """ |
|
1910 |
|
1911 if text is None: |
|
1912 ui.status(_("reading DAG from stdin\n")) |
|
1913 text = ui.fin.read() |
|
1914 |
|
1915 cl = repo.changelog |
|
1916 if len(cl) > 0: |
|
1917 raise error.Abort(_('repository is not empty')) |
|
1918 |
|
1919 # determine number of revs in DAG |
|
1920 total = 0 |
|
1921 for type, data in dagparser.parsedag(text): |
|
1922 if type == 'n': |
|
1923 total += 1 |
|
1924 |
|
1925 if mergeable_file: |
|
1926 linesperrev = 2 |
|
1927 # make a file with k lines per rev |
|
1928 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)] |
|
1929 initialmergedlines.append("") |
|
1930 |
|
1931 tags = [] |
|
1932 |
|
1933 wlock = lock = tr = None |
|
1934 try: |
|
1935 wlock = repo.wlock() |
|
1936 lock = repo.lock() |
|
1937 tr = repo.transaction("builddag") |
|
1938 |
|
1939 at = -1 |
|
1940 atbranch = 'default' |
|
1941 nodeids = [] |
|
1942 id = 0 |
|
1943 ui.progress(_('building'), id, unit=_('revisions'), total=total) |
|
1944 for type, data in dagparser.parsedag(text): |
|
1945 if type == 'n': |
|
1946 ui.note(('node %s\n' % str(data))) |
|
1947 id, ps = data |
|
1948 |
|
1949 files = [] |
|
1950 fctxs = {} |
|
1951 |
|
1952 p2 = None |
|
1953 if mergeable_file: |
|
1954 fn = "mf" |
|
1955 p1 = repo[ps[0]] |
|
1956 if len(ps) > 1: |
|
1957 p2 = repo[ps[1]] |
|
1958 pa = p1.ancestor(p2) |
|
1959 base, local, other = [x[fn].data() for x in (pa, p1, |
|
1960 p2)] |
|
1961 m3 = simplemerge.Merge3Text(base, local, other) |
|
1962 ml = [l.strip() for l in m3.merge_lines()] |
|
1963 ml.append("") |
|
1964 elif at > 0: |
|
1965 ml = p1[fn].data().split("\n") |
|
1966 else: |
|
1967 ml = initialmergedlines |
|
1968 ml[id * linesperrev] += " r%i" % id |
|
1969 mergedtext = "\n".join(ml) |
|
1970 files.append(fn) |
|
1971 fctxs[fn] = context.memfilectx(repo, fn, mergedtext) |
|
1972 |
|
1973 if overwritten_file: |
|
1974 fn = "of" |
|
1975 files.append(fn) |
|
1976 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id) |
|
1977 |
|
1978 if new_file: |
|
1979 fn = "nf%i" % id |
|
1980 files.append(fn) |
|
1981 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id) |
|
1982 if len(ps) > 1: |
|
1983 if not p2: |
|
1984 p2 = repo[ps[1]] |
|
1985 for fn in p2: |
|
1986 if fn.startswith("nf"): |
|
1987 files.append(fn) |
|
1988 fctxs[fn] = p2[fn] |
|
1989 |
|
1990 def fctxfn(repo, cx, path): |
|
1991 return fctxs.get(path) |
|
1992 |
|
1993 if len(ps) == 0 or ps[0] < 0: |
|
1994 pars = [None, None] |
|
1995 elif len(ps) == 1: |
|
1996 pars = [nodeids[ps[0]], None] |
|
1997 else: |
|
1998 pars = [nodeids[p] for p in ps] |
|
1999 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn, |
|
2000 date=(id, 0), |
|
2001 user="debugbuilddag", |
|
2002 extra={'branch': atbranch}) |
|
2003 nodeid = repo.commitctx(cx) |
|
2004 nodeids.append(nodeid) |
|
2005 at = id |
|
2006 elif type == 'l': |
|
2007 id, name = data |
|
2008 ui.note(('tag %s\n' % name)) |
|
2009 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name)) |
|
2010 elif type == 'a': |
|
2011 ui.note(('branch %s\n' % data)) |
|
2012 atbranch = data |
|
2013 ui.progress(_('building'), id, unit=_('revisions'), total=total) |
|
2014 tr.close() |
|
2015 |
|
2016 if tags: |
|
2017 repo.vfs.write("localtags", "".join(tags)) |
|
2018 finally: |
|
2019 ui.progress(_('building'), None) |
|
2020 release(tr, lock, wlock) |
|
2021 |
|
2022 @command('debugbundle', |
1868 @command('debugbundle', |
2023 [('a', 'all', None, _('show all details')), |
1869 [('a', 'all', None, _('show all details')), |
2024 ('', 'spec', None, _('print the bundlespec of the bundle'))], |
1870 ('', 'spec', None, _('print the bundlespec of the bundle'))], |
2025 _('FILE'), |
1871 _('FILE'), |
2026 norepo=True) |
1872 norepo=True) |