##// END OF EJS Templates
release: Merge default into stable for release preparation
marcink -
r37:897dca31 merge stable
parent child Browse files
Show More
@@ -1,6 +1,6 b''
1 [bumpversion]
1 [bumpversion]
2 current_version = 4.1.2
2 current_version = 4.2.0
3 message = release: Bump version {current_version} to {new_version}
3 message = release: Bump version {current_version} to {new_version}
4
4
5 [bumpversion:file:vcsserver/VERSION]
5 [bumpversion:file:vcsserver/VERSION]
6
6
@@ -1,16 +1,14 b''
1 [DEFAULT]
1 [DEFAULT]
2 done = false
2 done = false
3
3
4 [task:bump_version]
4 [task:bump_version]
5 done = true
5 done = true
6
6
7 [task:fixes_on_stable]
7 [task:fixes_on_stable]
8 done = true
9
8
10 [task:pip2nix_generated]
9 [task:pip2nix_generated]
11 done = true
12
10
13 [release]
11 [release]
14 state = prepared
12 state = in_progress
15 version = 4.1.2
13 version = 4.2.0
16
14
@@ -1,144 +1,145 b''
1 # Nix environment for the community edition
1 # Nix environment for the community edition
2 #
2 #
3 # This shall be as lean as possible, just producing the rhodecode-vcsserver
3 # This shall be as lean as possible, just producing the rhodecode-vcsserver
4 # derivation. For advanced tweaks to pimp up the development environment we use
4 # derivation. For advanced tweaks to pimp up the development environment we use
5 # "shell.nix" so that it does not have to clutter this file.
5 # "shell.nix" so that it does not have to clutter this file.
6
6
7 { pkgs ? (import <nixpkgs> {})
7 { pkgs ? (import <nixpkgs> {})
8 , pythonPackages ? "python27Packages"
8 , pythonPackages ? "python27Packages"
9 , pythonExternalOverrides ? self: super: {}
9 , pythonExternalOverrides ? self: super: {}
10 , doCheck ? true
10 , doCheck ? true
11 }:
11 }:
12
12
13 let pkgs_ = pkgs; in
13 let pkgs_ = pkgs; in
14
14
15 let
15 let
16 pkgs = pkgs_.overridePackages (self: super: {
16 pkgs = pkgs_.overridePackages (self: super: {
17 # Override subversion derivation to
17 # Override subversion derivation to
18 # - activate python bindings
18 # - activate python bindings
19 # - set version to 1.8
19 # - set version to 1.8
20 subversion = super.subversion18.override {
20 subversion = super.subversion18.override {
21 httpSupport = true;
21 httpSupport = true;
22 pythonBindings = true;
22 pythonBindings = true;
23 python = self.python27Packages.python;
23 python = self.python27Packages.python;
24 };
24 };
25 });
25 });
26
26
27 inherit (pkgs.lib) fix extends;
27 inherit (pkgs.lib) fix extends;
28
28
29 basePythonPackages = with builtins; if isAttrs pythonPackages
29 basePythonPackages = with builtins; if isAttrs pythonPackages
30 then pythonPackages
30 then pythonPackages
31 else getAttr pythonPackages pkgs;
31 else getAttr pythonPackages pkgs;
32
32
33 elem = builtins.elem;
33 elem = builtins.elem;
34 basename = path: with pkgs.lib; last (splitString "/" path);
34 basename = path: with pkgs.lib; last (splitString "/" path);
35 startsWith = prefix: full: let
35 startsWith = prefix: full: let
36 actualPrefix = builtins.substring 0 (builtins.stringLength prefix) full;
36 actualPrefix = builtins.substring 0 (builtins.stringLength prefix) full;
37 in actualPrefix == prefix;
37 in actualPrefix == prefix;
38
38
39 src-filter = path: type: with pkgs.lib;
39 src-filter = path: type: with pkgs.lib;
40 let
40 let
41 ext = last (splitString "." path);
41 ext = last (splitString "." path);
42 in
42 in
43 !elem (basename path) [
43 !elem (basename path) [
44 ".git" ".hg" "__pycache__" ".eggs" "node_modules"
44 ".git" ".hg" "__pycache__" ".eggs" "node_modules"
45 "build" "data" "tmp"] &&
45 "build" "data" "tmp"] &&
46 !elem ext ["egg-info" "pyc"] &&
46 !elem ext ["egg-info" "pyc"] &&
47 !startsWith "result" path;
47 !startsWith "result" path;
48
48
49 rhodecode-vcsserver-src = builtins.filterSource src-filter ./.;
49 rhodecode-vcsserver-src = builtins.filterSource src-filter ./.;
50
50
51 pythonGeneratedPackages = self: basePythonPackages.override (a: {
51 pythonGeneratedPackages = self: basePythonPackages.override (a: {
52 inherit self;
52 inherit self;
53 })
53 })
54 // (scopedImport {
54 // (scopedImport {
55 self = self;
55 self = self;
56 super = basePythonPackages;
56 super = basePythonPackages;
57 inherit pkgs;
57 inherit pkgs;
58 inherit (pkgs) fetchurl fetchgit;
58 inherit (pkgs) fetchurl fetchgit;
59 } ./pkgs/python-packages.nix);
59 } ./pkgs/python-packages.nix);
60
60
61 pythonOverrides = import ./pkgs/python-packages-overrides.nix {
61 pythonOverrides = import ./pkgs/python-packages-overrides.nix {
62 inherit
62 inherit
63 basePythonPackages
63 basePythonPackages
64 pkgs;
64 pkgs;
65 };
65 };
66
66
67 version = builtins.readFile ./vcsserver/VERSION;
67 version = builtins.readFile ./vcsserver/VERSION;
68
68
69 pythonLocalOverrides = self: super: {
69 pythonLocalOverrides = self: super: {
70 rhodecode-vcsserver = super.rhodecode-vcsserver.override (attrs: {
70 rhodecode-vcsserver = super.rhodecode-vcsserver.override (attrs: {
71 inherit
71 inherit
72 doCheck
72 doCheck
73 version;
73 version;
74 name = "rhodecode-vcsserver-${version}";
74 name = "rhodecode-vcsserver-${version}";
75 releaseName = "RhodeCodeVCSServer-${version}";
75 src = rhodecode-vcsserver-src;
76 src = rhodecode-vcsserver-src;
76
77
77 propagatedBuildInputs = attrs.propagatedBuildInputs ++ ([
78 propagatedBuildInputs = attrs.propagatedBuildInputs ++ ([
78 pkgs.git
79 pkgs.git
79 pkgs.subversion
80 pkgs.subversion
80 ]);
81 ]);
81
82
82 # TODO: johbo: Make a nicer way to expose the parts. Maybe
83 # TODO: johbo: Make a nicer way to expose the parts. Maybe
83 # pkgs/default.nix?
84 # pkgs/default.nix?
84 passthru = {
85 passthru = {
85 pythonPackages = self;
86 pythonPackages = self;
86 };
87 };
87
88
88 # Somewhat snappier setup of the development environment
89 # Somewhat snappier setup of the development environment
89 # TODO: move into shell.nix
90 # TODO: move into shell.nix
90 # TODO: think of supporting a stable path again, so that multiple shells
91 # TODO: think of supporting a stable path again, so that multiple shells
91 # can share it.
92 # can share it.
92 shellHook = ''
93 shellHook = ''
93 # Set locale
94 # Set locale
94 export LC_ALL="en_US.UTF-8"
95 export LC_ALL="en_US.UTF-8"
95
96
96 tmp_path=$(mktemp -d)
97 tmp_path=$(mktemp -d)
97 export PATH="$tmp_path/bin:$PATH"
98 export PATH="$tmp_path/bin:$PATH"
98 export PYTHONPATH="$tmp_path/${self.python.sitePackages}:$PYTHONPATH"
99 export PYTHONPATH="$tmp_path/${self.python.sitePackages}:$PYTHONPATH"
99 mkdir -p $tmp_path/${self.python.sitePackages}
100 mkdir -p $tmp_path/${self.python.sitePackages}
100 python setup.py develop --prefix $tmp_path --allow-hosts ""
101 python setup.py develop --prefix $tmp_path --allow-hosts ""
101 '';
102 '';
102
103
103 # Add VCSServer bin directory to path so that tests can find 'vcsserver'.
104 # Add VCSServer bin directory to path so that tests can find 'vcsserver'.
104 preCheck = ''
105 preCheck = ''
105 export PATH="$out/bin:$PATH"
106 export PATH="$out/bin:$PATH"
106 '';
107 '';
107
108
108 postInstall = ''
109 postInstall = ''
109 echo "Writing meta information for rccontrol to nix-support/rccontrol"
110 echo "Writing meta information for rccontrol to nix-support/rccontrol"
110 mkdir -p $out/nix-support/rccontrol
111 mkdir -p $out/nix-support/rccontrol
111 cp -v vcsserver/VERSION $out/nix-support/rccontrol/version
112 cp -v vcsserver/VERSION $out/nix-support/rccontrol/version
112 echo "DONE: Meta information for rccontrol written"
113 echo "DONE: Meta information for rccontrol written"
113
114
114 ln -s ${self.pyramid}/bin/* $out/bin #*/
115 ln -s ${self.pyramid}/bin/* $out/bin #*/
115 ln -s ${self.gunicorn}/bin/gunicorn $out/bin/
116 ln -s ${self.gunicorn}/bin/gunicorn $out/bin/
116
117
117 # Symlink version control utilities
118 # Symlink version control utilities
118 #
119 #
119 # We ensure that always the correct version is available as a symlink.
120 # We ensure that always the correct version is available as a symlink.
120 # So that users calling them via the profile path will always use the
121 # So that users calling them via the profile path will always use the
121 # correct version.
122 # correct version.
122 ln -s ${pkgs.git}/bin/git $out/bin
123 ln -s ${pkgs.git}/bin/git $out/bin
123 ln -s ${self.mercurial}/bin/hg $out/bin
124 ln -s ${self.mercurial}/bin/hg $out/bin
124 ln -s ${pkgs.subversion}/bin/svn* $out/bin
125 ln -s ${pkgs.subversion}/bin/svn* $out/bin
125
126
126 for file in $out/bin/*; do #*/
127 for file in $out/bin/*; do #*/
127 wrapProgram $file \
128 wrapProgram $file \
128 --prefix PYTHONPATH : $PYTHONPATH \
129 --prefix PYTHONPATH : $PYTHONPATH \
129 --set PYTHONHASHSEED random
130 --set PYTHONHASHSEED random
130 done
131 done
131 '';
132 '';
132
133
133 });
134 });
134 };
135 };
135
136
136 # Apply all overrides and fix the final package set
137 # Apply all overrides and fix the final package set
137 myPythonPackages =
138 myPythonPackages =
138 (fix
139 (fix
139 (extends pythonExternalOverrides
140 (extends pythonExternalOverrides
140 (extends pythonLocalOverrides
141 (extends pythonLocalOverrides
141 (extends pythonOverrides
142 (extends pythonOverrides
142 pythonGeneratedPackages))));
143 pythonGeneratedPackages))));
143
144
144 in myPythonPackages.rhodecode-vcsserver
145 in myPythonPackages.rhodecode-vcsserver
@@ -1,363 +1,363 b''
1 {
1 {
2 Beaker = super.buildPythonPackage {
2 Beaker = super.buildPythonPackage {
3 name = "Beaker-1.7.0";
3 name = "Beaker-1.7.0";
4 buildInputs = with self; [];
4 buildInputs = with self; [];
5 doCheck = false;
5 doCheck = false;
6 propagatedBuildInputs = with self; [];
6 propagatedBuildInputs = with self; [];
7 src = fetchurl {
7 src = fetchurl {
8 url = "https://pypi.python.org/packages/97/8e/409d2e7c009b8aa803dc9e6f239f1db7c3cdf578249087a404e7c27a505d/Beaker-1.7.0.tar.gz";
8 url = "https://pypi.python.org/packages/97/8e/409d2e7c009b8aa803dc9e6f239f1db7c3cdf578249087a404e7c27a505d/Beaker-1.7.0.tar.gz";
9 md5 = "386be3f7fe427358881eee4622b428b3";
9 md5 = "386be3f7fe427358881eee4622b428b3";
10 };
10 };
11 };
11 };
12 Jinja2 = super.buildPythonPackage {
12 Jinja2 = super.buildPythonPackage {
13 name = "Jinja2-2.8";
13 name = "Jinja2-2.8";
14 buildInputs = with self; [];
14 buildInputs = with self; [];
15 doCheck = false;
15 doCheck = false;
16 propagatedBuildInputs = with self; [MarkupSafe];
16 propagatedBuildInputs = with self; [MarkupSafe];
17 src = fetchurl {
17 src = fetchurl {
18 url = "https://pypi.python.org/packages/f2/2f/0b98b06a345a761bec91a079ccae392d282690c2d8272e708f4d10829e22/Jinja2-2.8.tar.gz";
18 url = "https://pypi.python.org/packages/f2/2f/0b98b06a345a761bec91a079ccae392d282690c2d8272e708f4d10829e22/Jinja2-2.8.tar.gz";
19 md5 = "edb51693fe22c53cee5403775c71a99e";
19 md5 = "edb51693fe22c53cee5403775c71a99e";
20 };
20 };
21 };
21 };
22 Mako = super.buildPythonPackage {
22 Mako = super.buildPythonPackage {
23 name = "Mako-1.0.4";
23 name = "Mako-1.0.4";
24 buildInputs = with self; [];
24 buildInputs = with self; [];
25 doCheck = false;
25 doCheck = false;
26 propagatedBuildInputs = with self; [MarkupSafe];
26 propagatedBuildInputs = with self; [MarkupSafe];
27 src = fetchurl {
27 src = fetchurl {
28 url = "https://pypi.python.org/packages/7a/ae/925434246ee90b42e8ef57d3b30a0ab7caf9a2de3e449b876c56dcb48155/Mako-1.0.4.tar.gz";
28 url = "https://pypi.python.org/packages/7a/ae/925434246ee90b42e8ef57d3b30a0ab7caf9a2de3e449b876c56dcb48155/Mako-1.0.4.tar.gz";
29 md5 = "c5fc31a323dd4990683d2f2da02d4e20";
29 md5 = "c5fc31a323dd4990683d2f2da02d4e20";
30 };
30 };
31 };
31 };
32 MarkupSafe = super.buildPythonPackage {
32 MarkupSafe = super.buildPythonPackage {
33 name = "MarkupSafe-0.23";
33 name = "MarkupSafe-0.23";
34 buildInputs = with self; [];
34 buildInputs = with self; [];
35 doCheck = false;
35 doCheck = false;
36 propagatedBuildInputs = with self; [];
36 propagatedBuildInputs = with self; [];
37 src = fetchurl {
37 src = fetchurl {
38 url = "https://pypi.python.org/packages/c0/41/bae1254e0396c0cc8cf1751cb7d9afc90a602353695af5952530482c963f/MarkupSafe-0.23.tar.gz";
38 url = "https://pypi.python.org/packages/c0/41/bae1254e0396c0cc8cf1751cb7d9afc90a602353695af5952530482c963f/MarkupSafe-0.23.tar.gz";
39 md5 = "f5ab3deee4c37cd6a922fb81e730da6e";
39 md5 = "f5ab3deee4c37cd6a922fb81e730da6e";
40 };
40 };
41 };
41 };
42 PasteDeploy = super.buildPythonPackage {
42 PasteDeploy = super.buildPythonPackage {
43 name = "PasteDeploy-1.5.2";
43 name = "PasteDeploy-1.5.2";
44 buildInputs = with self; [];
44 buildInputs = with self; [];
45 doCheck = false;
45 doCheck = false;
46 propagatedBuildInputs = with self; [];
46 propagatedBuildInputs = with self; [];
47 src = fetchurl {
47 src = fetchurl {
48 url = "https://pypi.python.org/packages/0f/90/8e20cdae206c543ea10793cbf4136eb9a8b3f417e04e40a29d72d9922cbd/PasteDeploy-1.5.2.tar.gz";
48 url = "https://pypi.python.org/packages/0f/90/8e20cdae206c543ea10793cbf4136eb9a8b3f417e04e40a29d72d9922cbd/PasteDeploy-1.5.2.tar.gz";
49 md5 = "352b7205c78c8de4987578d19431af3b";
49 md5 = "352b7205c78c8de4987578d19431af3b";
50 };
50 };
51 };
51 };
52 Pyro4 = super.buildPythonPackage {
52 Pyro4 = super.buildPythonPackage {
53 name = "Pyro4-4.41";
53 name = "Pyro4-4.41";
54 buildInputs = with self; [];
54 buildInputs = with self; [];
55 doCheck = false;
55 doCheck = false;
56 propagatedBuildInputs = with self; [serpent];
56 propagatedBuildInputs = with self; [serpent];
57 src = fetchurl {
57 src = fetchurl {
58 url = "https://pypi.python.org/packages/56/2b/89b566b4bf3e7f8ba790db2d1223852f8cb454c52cab7693dd41f608ca2a/Pyro4-4.41.tar.gz";
58 url = "https://pypi.python.org/packages/56/2b/89b566b4bf3e7f8ba790db2d1223852f8cb454c52cab7693dd41f608ca2a/Pyro4-4.41.tar.gz";
59 md5 = "ed69e9bfafa9c06c049a87cb0c4c2b6c";
59 md5 = "ed69e9bfafa9c06c049a87cb0c4c2b6c";
60 };
60 };
61 };
61 };
62 WebOb = super.buildPythonPackage {
62 WebOb = super.buildPythonPackage {
63 name = "WebOb-1.3.1";
63 name = "WebOb-1.3.1";
64 buildInputs = with self; [];
64 buildInputs = with self; [];
65 doCheck = false;
65 doCheck = false;
66 propagatedBuildInputs = with self; [];
66 propagatedBuildInputs = with self; [];
67 src = fetchurl {
67 src = fetchurl {
68 url = "https://pypi.python.org/packages/16/78/adfc0380b8a0d75b2d543fa7085ba98a573b1ae486d9def88d172b81b9fa/WebOb-1.3.1.tar.gz";
68 url = "https://pypi.python.org/packages/16/78/adfc0380b8a0d75b2d543fa7085ba98a573b1ae486d9def88d172b81b9fa/WebOb-1.3.1.tar.gz";
69 md5 = "20918251c5726956ba8fef22d1556177";
69 md5 = "20918251c5726956ba8fef22d1556177";
70 };
70 };
71 };
71 };
72 WebTest = super.buildPythonPackage {
72 WebTest = super.buildPythonPackage {
73 name = "WebTest-1.4.3";
73 name = "WebTest-1.4.3";
74 buildInputs = with self; [];
74 buildInputs = with self; [];
75 doCheck = false;
75 doCheck = false;
76 propagatedBuildInputs = with self; [WebOb];
76 propagatedBuildInputs = with self; [WebOb];
77 src = fetchurl {
77 src = fetchurl {
78 url = "https://pypi.python.org/packages/51/3d/84fd0f628df10b30c7db87895f56d0158e5411206b721ca903cb51bfd948/WebTest-1.4.3.zip";
78 url = "https://pypi.python.org/packages/51/3d/84fd0f628df10b30c7db87895f56d0158e5411206b721ca903cb51bfd948/WebTest-1.4.3.zip";
79 md5 = "631ce728bed92c681a4020a36adbc353";
79 md5 = "631ce728bed92c681a4020a36adbc353";
80 };
80 };
81 };
81 };
82 configobj = super.buildPythonPackage {
82 configobj = super.buildPythonPackage {
83 name = "configobj-5.0.6";
83 name = "configobj-5.0.6";
84 buildInputs = with self; [];
84 buildInputs = with self; [];
85 doCheck = false;
85 doCheck = false;
86 propagatedBuildInputs = with self; [six];
86 propagatedBuildInputs = with self; [six];
87 src = fetchurl {
87 src = fetchurl {
88 url = "https://pypi.python.org/packages/64/61/079eb60459c44929e684fa7d9e2fdca403f67d64dd9dbac27296be2e0fab/configobj-5.0.6.tar.gz";
88 url = "https://pypi.python.org/packages/64/61/079eb60459c44929e684fa7d9e2fdca403f67d64dd9dbac27296be2e0fab/configobj-5.0.6.tar.gz";
89 md5 = "e472a3a1c2a67bb0ec9b5d54c13a47d6";
89 md5 = "e472a3a1c2a67bb0ec9b5d54c13a47d6";
90 };
90 };
91 };
91 };
92 dulwich = super.buildPythonPackage {
92 dulwich = super.buildPythonPackage {
93 name = "dulwich-0.12.0";
93 name = "dulwich-0.13.0";
94 buildInputs = with self; [];
94 buildInputs = with self; [];
95 doCheck = false;
95 doCheck = false;
96 propagatedBuildInputs = with self; [];
96 propagatedBuildInputs = with self; [];
97 src = fetchurl {
97 src = fetchurl {
98 url = "https://pypi.python.org/packages/6f/04/fbe561b6d45c0ec758330d5b7f5ba4b6cb4f1ca1ab49859d2fc16320da75/dulwich-0.12.0.tar.gz";
98 url = "https://pypi.python.org/packages/84/95/732d280eee829dacc954e8109f97b47abcadcca472c2ab013e1635eb4792/dulwich-0.13.0.tar.gz";
99 md5 = "f3a8a12bd9f9dd8c233e18f3d49436fa";
99 md5 = "6dede0626657c2bd08f48ca1221eea91";
100 };
100 };
101 };
101 };
102 greenlet = super.buildPythonPackage {
102 greenlet = super.buildPythonPackage {
103 name = "greenlet-0.4.7";
103 name = "greenlet-0.4.7";
104 buildInputs = with self; [];
104 buildInputs = with self; [];
105 doCheck = false;
105 doCheck = false;
106 propagatedBuildInputs = with self; [];
106 propagatedBuildInputs = with self; [];
107 src = fetchurl {
107 src = fetchurl {
108 url = "https://pypi.python.org/packages/7a/9f/a1a0d9bdf3203ae1502c5a8434fe89d323599d78a106985bc327351a69d4/greenlet-0.4.7.zip";
108 url = "https://pypi.python.org/packages/7a/9f/a1a0d9bdf3203ae1502c5a8434fe89d323599d78a106985bc327351a69d4/greenlet-0.4.7.zip";
109 md5 = "c2333a8ff30fa75c5d5ec0e67b461086";
109 md5 = "c2333a8ff30fa75c5d5ec0e67b461086";
110 };
110 };
111 };
111 };
112 gunicorn = super.buildPythonPackage {
112 gunicorn = super.buildPythonPackage {
113 name = "gunicorn-19.6.0";
113 name = "gunicorn-19.6.0";
114 buildInputs = with self; [];
114 buildInputs = with self; [];
115 doCheck = false;
115 doCheck = false;
116 propagatedBuildInputs = with self; [];
116 propagatedBuildInputs = with self; [];
117 src = fetchurl {
117 src = fetchurl {
118 url = "https://pypi.python.org/packages/84/ce/7ea5396efad1cef682bbc4068e72a0276341d9d9d0f501da609fab9fcb80/gunicorn-19.6.0.tar.gz";
118 url = "https://pypi.python.org/packages/84/ce/7ea5396efad1cef682bbc4068e72a0276341d9d9d0f501da609fab9fcb80/gunicorn-19.6.0.tar.gz";
119 md5 = "338e5e8a83ea0f0625f768dba4597530";
119 md5 = "338e5e8a83ea0f0625f768dba4597530";
120 };
120 };
121 };
121 };
122 hgsubversion = super.buildPythonPackage {
122 hgsubversion = super.buildPythonPackage {
123 name = "hgsubversion-1.8.6";
123 name = "hgsubversion-1.8.6";
124 buildInputs = with self; [];
124 buildInputs = with self; [];
125 doCheck = false;
125 doCheck = false;
126 propagatedBuildInputs = with self; [mercurial subvertpy];
126 propagatedBuildInputs = with self; [mercurial subvertpy];
127 src = fetchurl {
127 src = fetchurl {
128 url = "https://pypi.python.org/packages/ce/97/032e5093ad250e9908cea04395cbddb6902d587f712a79b53b2d778bdfdd/hgsubversion-1.8.6.tar.gz";
128 url = "https://pypi.python.org/packages/ce/97/032e5093ad250e9908cea04395cbddb6902d587f712a79b53b2d778bdfdd/hgsubversion-1.8.6.tar.gz";
129 md5 = "9310cb266031cf8d0779885782a84a5b";
129 md5 = "9310cb266031cf8d0779885782a84a5b";
130 };
130 };
131 };
131 };
132 infrae.cache = super.buildPythonPackage {
132 infrae.cache = super.buildPythonPackage {
133 name = "infrae.cache-1.0.1";
133 name = "infrae.cache-1.0.1";
134 buildInputs = with self; [];
134 buildInputs = with self; [];
135 doCheck = false;
135 doCheck = false;
136 propagatedBuildInputs = with self; [Beaker repoze.lru];
136 propagatedBuildInputs = with self; [Beaker repoze.lru];
137 src = fetchurl {
137 src = fetchurl {
138 url = "https://pypi.python.org/packages/bb/f0/e7d5e984cf6592fd2807dc7bc44a93f9d18e04e6a61f87fdfb2622422d74/infrae.cache-1.0.1.tar.gz";
138 url = "https://pypi.python.org/packages/bb/f0/e7d5e984cf6592fd2807dc7bc44a93f9d18e04e6a61f87fdfb2622422d74/infrae.cache-1.0.1.tar.gz";
139 md5 = "b09076a766747e6ed2a755cc62088e32";
139 md5 = "b09076a766747e6ed2a755cc62088e32";
140 };
140 };
141 };
141 };
142 mercurial = super.buildPythonPackage {
142 mercurial = super.buildPythonPackage {
143 name = "mercurial-3.8.3";
143 name = "mercurial-3.8.3";
144 buildInputs = with self; [];
144 buildInputs = with self; [];
145 doCheck = false;
145 doCheck = false;
146 propagatedBuildInputs = with self; [];
146 propagatedBuildInputs = with self; [];
147 src = fetchurl {
147 src = fetchurl {
148 url = "https://pypi.python.org/packages/56/bc/af1561195d43638d44bc3ac286c21f187430966234bee1f235711d80dfb6/mercurial-3.8.3.tar.gz";
148 url = "https://pypi.python.org/packages/56/bc/af1561195d43638d44bc3ac286c21f187430966234bee1f235711d80dfb6/mercurial-3.8.3.tar.gz";
149 md5 = "97aced7018614eeccc9621a3dea35fda";
149 md5 = "97aced7018614eeccc9621a3dea35fda";
150 };
150 };
151 };
151 };
152 mock = super.buildPythonPackage {
152 mock = super.buildPythonPackage {
153 name = "mock-1.0.1";
153 name = "mock-1.0.1";
154 buildInputs = with self; [];
154 buildInputs = with self; [];
155 doCheck = false;
155 doCheck = false;
156 propagatedBuildInputs = with self; [];
156 propagatedBuildInputs = with self; [];
157 src = fetchurl {
157 src = fetchurl {
158 url = "https://pypi.python.org/packages/15/45/30273ee91feb60dabb8fbb2da7868520525f02cf910279b3047182feed80/mock-1.0.1.zip";
158 url = "https://pypi.python.org/packages/15/45/30273ee91feb60dabb8fbb2da7868520525f02cf910279b3047182feed80/mock-1.0.1.zip";
159 md5 = "869f08d003c289a97c1a6610faf5e913";
159 md5 = "869f08d003c289a97c1a6610faf5e913";
160 };
160 };
161 };
161 };
162 msgpack-python = super.buildPythonPackage {
162 msgpack-python = super.buildPythonPackage {
163 name = "msgpack-python-0.4.6";
163 name = "msgpack-python-0.4.6";
164 buildInputs = with self; [];
164 buildInputs = with self; [];
165 doCheck = false;
165 doCheck = false;
166 propagatedBuildInputs = with self; [];
166 propagatedBuildInputs = with self; [];
167 src = fetchurl {
167 src = fetchurl {
168 url = "https://pypi.python.org/packages/15/ce/ff2840885789ef8035f66cd506ea05bdb228340307d5e71a7b1e3f82224c/msgpack-python-0.4.6.tar.gz";
168 url = "https://pypi.python.org/packages/15/ce/ff2840885789ef8035f66cd506ea05bdb228340307d5e71a7b1e3f82224c/msgpack-python-0.4.6.tar.gz";
169 md5 = "8b317669314cf1bc881716cccdaccb30";
169 md5 = "8b317669314cf1bc881716cccdaccb30";
170 };
170 };
171 };
171 };
172 py = super.buildPythonPackage {
172 py = super.buildPythonPackage {
173 name = "py-1.4.29";
173 name = "py-1.4.29";
174 buildInputs = with self; [];
174 buildInputs = with self; [];
175 doCheck = false;
175 doCheck = false;
176 propagatedBuildInputs = with self; [];
176 propagatedBuildInputs = with self; [];
177 src = fetchurl {
177 src = fetchurl {
178 url = "https://pypi.python.org/packages/2a/bc/a1a4a332ac10069b8e5e25136a35e08a03f01fd6ab03d819889d79a1fd65/py-1.4.29.tar.gz";
178 url = "https://pypi.python.org/packages/2a/bc/a1a4a332ac10069b8e5e25136a35e08a03f01fd6ab03d819889d79a1fd65/py-1.4.29.tar.gz";
179 md5 = "c28e0accba523a29b35a48bb703fb96c";
179 md5 = "c28e0accba523a29b35a48bb703fb96c";
180 };
180 };
181 };
181 };
182 pyramid = super.buildPythonPackage {
182 pyramid = super.buildPythonPackage {
183 name = "pyramid-1.6.1";
183 name = "pyramid-1.6.1";
184 buildInputs = with self; [];
184 buildInputs = with self; [];
185 doCheck = false;
185 doCheck = false;
186 propagatedBuildInputs = with self; [setuptools WebOb repoze.lru zope.interface zope.deprecation venusian translationstring PasteDeploy];
186 propagatedBuildInputs = with self; [setuptools WebOb repoze.lru zope.interface zope.deprecation venusian translationstring PasteDeploy];
187 src = fetchurl {
187 src = fetchurl {
188 url = "https://pypi.python.org/packages/30/b3/fcc4a2a4800cbf21989e00454b5828cf1f7fe35c63e0810b350e56d4c475/pyramid-1.6.1.tar.gz";
188 url = "https://pypi.python.org/packages/30/b3/fcc4a2a4800cbf21989e00454b5828cf1f7fe35c63e0810b350e56d4c475/pyramid-1.6.1.tar.gz";
189 md5 = "b18688ff3cc33efdbb098a35b45dd122";
189 md5 = "b18688ff3cc33efdbb098a35b45dd122";
190 };
190 };
191 };
191 };
192 pyramid-jinja2 = super.buildPythonPackage {
192 pyramid-jinja2 = super.buildPythonPackage {
193 name = "pyramid-jinja2-2.5";
193 name = "pyramid-jinja2-2.5";
194 buildInputs = with self; [];
194 buildInputs = with self; [];
195 doCheck = false;
195 doCheck = false;
196 propagatedBuildInputs = with self; [pyramid zope.deprecation Jinja2 MarkupSafe];
196 propagatedBuildInputs = with self; [pyramid zope.deprecation Jinja2 MarkupSafe];
197 src = fetchurl {
197 src = fetchurl {
198 url = "https://pypi.python.org/packages/a1/80/595e26ffab7deba7208676b6936b7e5a721875710f982e59899013cae1ed/pyramid_jinja2-2.5.tar.gz";
198 url = "https://pypi.python.org/packages/a1/80/595e26ffab7deba7208676b6936b7e5a721875710f982e59899013cae1ed/pyramid_jinja2-2.5.tar.gz";
199 md5 = "07cb6547204ac5e6f0b22a954ccee928";
199 md5 = "07cb6547204ac5e6f0b22a954ccee928";
200 };
200 };
201 };
201 };
202 pyramid-mako = super.buildPythonPackage {
202 pyramid-mako = super.buildPythonPackage {
203 name = "pyramid-mako-1.0.2";
203 name = "pyramid-mako-1.0.2";
204 buildInputs = with self; [];
204 buildInputs = with self; [];
205 doCheck = false;
205 doCheck = false;
206 propagatedBuildInputs = with self; [pyramid Mako];
206 propagatedBuildInputs = with self; [pyramid Mako];
207 src = fetchurl {
207 src = fetchurl {
208 url = "https://pypi.python.org/packages/f1/92/7e69bcf09676d286a71cb3bbb887b16595b96f9ba7adbdc239ffdd4b1eb9/pyramid_mako-1.0.2.tar.gz";
208 url = "https://pypi.python.org/packages/f1/92/7e69bcf09676d286a71cb3bbb887b16595b96f9ba7adbdc239ffdd4b1eb9/pyramid_mako-1.0.2.tar.gz";
209 md5 = "ee25343a97eb76bd90abdc2a774eb48a";
209 md5 = "ee25343a97eb76bd90abdc2a774eb48a";
210 };
210 };
211 };
211 };
212 pytest = super.buildPythonPackage {
212 pytest = super.buildPythonPackage {
213 name = "pytest-2.8.5";
213 name = "pytest-2.8.5";
214 buildInputs = with self; [];
214 buildInputs = with self; [];
215 doCheck = false;
215 doCheck = false;
216 propagatedBuildInputs = with self; [py];
216 propagatedBuildInputs = with self; [py];
217 src = fetchurl {
217 src = fetchurl {
218 url = "https://pypi.python.org/packages/b1/3d/d7ea9b0c51e0cacded856e49859f0a13452747491e842c236bbab3714afe/pytest-2.8.5.zip";
218 url = "https://pypi.python.org/packages/b1/3d/d7ea9b0c51e0cacded856e49859f0a13452747491e842c236bbab3714afe/pytest-2.8.5.zip";
219 md5 = "8493b06f700862f1294298d6c1b715a9";
219 md5 = "8493b06f700862f1294298d6c1b715a9";
220 };
220 };
221 };
221 };
222 repoze.lru = super.buildPythonPackage {
222 repoze.lru = super.buildPythonPackage {
223 name = "repoze.lru-0.6";
223 name = "repoze.lru-0.6";
224 buildInputs = with self; [];
224 buildInputs = with self; [];
225 doCheck = false;
225 doCheck = false;
226 propagatedBuildInputs = with self; [];
226 propagatedBuildInputs = with self; [];
227 src = fetchurl {
227 src = fetchurl {
228 url = "https://pypi.python.org/packages/6e/1e/aa15cc90217e086dc8769872c8778b409812ff036bf021b15795638939e4/repoze.lru-0.6.tar.gz";
228 url = "https://pypi.python.org/packages/6e/1e/aa15cc90217e086dc8769872c8778b409812ff036bf021b15795638939e4/repoze.lru-0.6.tar.gz";
229 md5 = "2c3b64b17a8e18b405f55d46173e14dd";
229 md5 = "2c3b64b17a8e18b405f55d46173e14dd";
230 };
230 };
231 };
231 };
232 rhodecode-vcsserver = super.buildPythonPackage {
232 rhodecode-vcsserver = super.buildPythonPackage {
233 name = "rhodecode-vcsserver-4.1.2";
233 name = "rhodecode-vcsserver-4.1.2";
234 buildInputs = with self; [mock pytest WebTest];
234 buildInputs = with self; [mock pytest WebTest];
235 doCheck = true;
235 doCheck = true;
236 propagatedBuildInputs = with self; [configobj dulwich hgsubversion infrae.cache mercurial msgpack-python pyramid Pyro4 simplejson subprocess32 waitress WebOb];
236 propagatedBuildInputs = with self; [configobj dulwich hgsubversion infrae.cache mercurial msgpack-python pyramid Pyro4 simplejson subprocess32 waitress WebOb];
237 src = ./.;
237 src = ./.;
238 };
238 };
239 serpent = super.buildPythonPackage {
239 serpent = super.buildPythonPackage {
240 name = "serpent-1.12";
240 name = "serpent-1.12";
241 buildInputs = with self; [];
241 buildInputs = with self; [];
242 doCheck = false;
242 doCheck = false;
243 propagatedBuildInputs = with self; [];
243 propagatedBuildInputs = with self; [];
244 src = fetchurl {
244 src = fetchurl {
245 url = "https://pypi.python.org/packages/3b/19/1e0e83b47c09edaef8398655088036e7e67386b5c48770218ebb339fbbd5/serpent-1.12.tar.gz";
245 url = "https://pypi.python.org/packages/3b/19/1e0e83b47c09edaef8398655088036e7e67386b5c48770218ebb339fbbd5/serpent-1.12.tar.gz";
246 md5 = "05869ac7b062828b34f8f927f0457b65";
246 md5 = "05869ac7b062828b34f8f927f0457b65";
247 };
247 };
248 };
248 };
249 setuptools = super.buildPythonPackage {
249 setuptools = super.buildPythonPackage {
250 name = "setuptools-20.8.1";
250 name = "setuptools-20.8.1";
251 buildInputs = with self; [];
251 buildInputs = with self; [];
252 doCheck = false;
252 doCheck = false;
253 propagatedBuildInputs = with self; [];
253 propagatedBuildInputs = with self; [];
254 src = fetchurl {
254 src = fetchurl {
255 url = "https://pypi.python.org/packages/c4/19/c1bdc88b53da654df43770f941079dbab4e4788c2dcb5658fb86259894c7/setuptools-20.8.1.zip";
255 url = "https://pypi.python.org/packages/c4/19/c1bdc88b53da654df43770f941079dbab4e4788c2dcb5658fb86259894c7/setuptools-20.8.1.zip";
256 md5 = "fe58a5cac0df20bb83942b252a4b0543";
256 md5 = "fe58a5cac0df20bb83942b252a4b0543";
257 };
257 };
258 };
258 };
259 simplejson = super.buildPythonPackage {
259 simplejson = super.buildPythonPackage {
260 name = "simplejson-3.7.2";
260 name = "simplejson-3.7.2";
261 buildInputs = with self; [];
261 buildInputs = with self; [];
262 doCheck = false;
262 doCheck = false;
263 propagatedBuildInputs = with self; [];
263 propagatedBuildInputs = with self; [];
264 src = fetchurl {
264 src = fetchurl {
265 url = "https://pypi.python.org/packages/6d/89/7f13f099344eea9d6722779a1f165087cb559598107844b1ac5dbd831fb1/simplejson-3.7.2.tar.gz";
265 url = "https://pypi.python.org/packages/6d/89/7f13f099344eea9d6722779a1f165087cb559598107844b1ac5dbd831fb1/simplejson-3.7.2.tar.gz";
266 md5 = "a5fc7d05d4cb38492285553def5d4b46";
266 md5 = "a5fc7d05d4cb38492285553def5d4b46";
267 };
267 };
268 };
268 };
269 six = super.buildPythonPackage {
269 six = super.buildPythonPackage {
270 name = "six-1.9.0";
270 name = "six-1.9.0";
271 buildInputs = with self; [];
271 buildInputs = with self; [];
272 doCheck = false;
272 doCheck = false;
273 propagatedBuildInputs = with self; [];
273 propagatedBuildInputs = with self; [];
274 src = fetchurl {
274 src = fetchurl {
275 url = "https://pypi.python.org/packages/16/64/1dc5e5976b17466fd7d712e59cbe9fb1e18bec153109e5ba3ed6c9102f1a/six-1.9.0.tar.gz";
275 url = "https://pypi.python.org/packages/16/64/1dc5e5976b17466fd7d712e59cbe9fb1e18bec153109e5ba3ed6c9102f1a/six-1.9.0.tar.gz";
276 md5 = "476881ef4012262dfc8adc645ee786c4";
276 md5 = "476881ef4012262dfc8adc645ee786c4";
277 };
277 };
278 };
278 };
279 subprocess32 = super.buildPythonPackage {
279 subprocess32 = super.buildPythonPackage {
280 name = "subprocess32-3.2.6";
280 name = "subprocess32-3.2.6";
281 buildInputs = with self; [];
281 buildInputs = with self; [];
282 doCheck = false;
282 doCheck = false;
283 propagatedBuildInputs = with self; [];
283 propagatedBuildInputs = with self; [];
284 src = fetchurl {
284 src = fetchurl {
285 url = "https://pypi.python.org/packages/28/8d/33ccbff51053f59ae6c357310cac0e79246bbed1d345ecc6188b176d72c3/subprocess32-3.2.6.tar.gz";
285 url = "https://pypi.python.org/packages/28/8d/33ccbff51053f59ae6c357310cac0e79246bbed1d345ecc6188b176d72c3/subprocess32-3.2.6.tar.gz";
286 md5 = "754c5ab9f533e764f931136974b618f1";
286 md5 = "754c5ab9f533e764f931136974b618f1";
287 };
287 };
288 };
288 };
289 subvertpy = super.buildPythonPackage {
289 subvertpy = super.buildPythonPackage {
290 name = "subvertpy-0.9.3";
290 name = "subvertpy-0.9.3";
291 buildInputs = with self; [];
291 buildInputs = with self; [];
292 doCheck = false;
292 doCheck = false;
293 propagatedBuildInputs = with self; [];
293 propagatedBuildInputs = with self; [];
294 src = fetchurl {
294 src = fetchurl {
295 url = "https://github.com/jelmer/subvertpy/archive/subvertpy-0.9.3.tar.gz";
295 url = "https://github.com/jelmer/subvertpy/archive/subvertpy-0.9.3.tar.gz";
296 md5 = "7b745a47128050ea5a73efcd913ec1cf";
296 md5 = "7b745a47128050ea5a73efcd913ec1cf";
297 };
297 };
298 };
298 };
299 translationstring = super.buildPythonPackage {
299 translationstring = super.buildPythonPackage {
300 name = "translationstring-1.3";
300 name = "translationstring-1.3";
301 buildInputs = with self; [];
301 buildInputs = with self; [];
302 doCheck = false;
302 doCheck = false;
303 propagatedBuildInputs = with self; [];
303 propagatedBuildInputs = with self; [];
304 src = fetchurl {
304 src = fetchurl {
305 url = "https://pypi.python.org/packages/5e/eb/bee578cc150b44c653b63f5ebe258b5d0d812ddac12497e5f80fcad5d0b4/translationstring-1.3.tar.gz";
305 url = "https://pypi.python.org/packages/5e/eb/bee578cc150b44c653b63f5ebe258b5d0d812ddac12497e5f80fcad5d0b4/translationstring-1.3.tar.gz";
306 md5 = "a4b62e0f3c189c783a1685b3027f7c90";
306 md5 = "a4b62e0f3c189c783a1685b3027f7c90";
307 };
307 };
308 };
308 };
309 venusian = super.buildPythonPackage {
309 venusian = super.buildPythonPackage {
310 name = "venusian-1.0";
310 name = "venusian-1.0";
311 buildInputs = with self; [];
311 buildInputs = with self; [];
312 doCheck = false;
312 doCheck = false;
313 propagatedBuildInputs = with self; [];
313 propagatedBuildInputs = with self; [];
314 src = fetchurl {
314 src = fetchurl {
315 url = "https://pypi.python.org/packages/86/20/1948e0dfc4930ddde3da8c33612f6a5717c0b4bc28f591a5c5cf014dd390/venusian-1.0.tar.gz";
315 url = "https://pypi.python.org/packages/86/20/1948e0dfc4930ddde3da8c33612f6a5717c0b4bc28f591a5c5cf014dd390/venusian-1.0.tar.gz";
316 md5 = "dccf2eafb7113759d60c86faf5538756";
316 md5 = "dccf2eafb7113759d60c86faf5538756";
317 };
317 };
318 };
318 };
319 waitress = super.buildPythonPackage {
319 waitress = super.buildPythonPackage {
320 name = "waitress-0.8.9";
320 name = "waitress-0.8.9";
321 buildInputs = with self; [];
321 buildInputs = with self; [];
322 doCheck = false;
322 doCheck = false;
323 propagatedBuildInputs = with self; [setuptools];
323 propagatedBuildInputs = with self; [setuptools];
324 src = fetchurl {
324 src = fetchurl {
325 url = "https://pypi.python.org/packages/ee/65/fc9dee74a909a1187ca51e4f15ad9c4d35476e4ab5813f73421505c48053/waitress-0.8.9.tar.gz";
325 url = "https://pypi.python.org/packages/ee/65/fc9dee74a909a1187ca51e4f15ad9c4d35476e4ab5813f73421505c48053/waitress-0.8.9.tar.gz";
326 md5 = "da3f2e62b3676be5dd630703a68e2a04";
326 md5 = "da3f2e62b3676be5dd630703a68e2a04";
327 };
327 };
328 };
328 };
329 wheel = super.buildPythonPackage {
329 wheel = super.buildPythonPackage {
330 name = "wheel-0.29.0";
330 name = "wheel-0.29.0";
331 buildInputs = with self; [];
331 buildInputs = with self; [];
332 doCheck = false;
332 doCheck = false;
333 propagatedBuildInputs = with self; [];
333 propagatedBuildInputs = with self; [];
334 src = fetchurl {
334 src = fetchurl {
335 url = "https://pypi.python.org/packages/c9/1d/bd19e691fd4cfe908c76c429fe6e4436c9e83583c4414b54f6c85471954a/wheel-0.29.0.tar.gz";
335 url = "https://pypi.python.org/packages/c9/1d/bd19e691fd4cfe908c76c429fe6e4436c9e83583c4414b54f6c85471954a/wheel-0.29.0.tar.gz";
336 md5 = "555a67e4507cedee23a0deb9651e452f";
336 md5 = "555a67e4507cedee23a0deb9651e452f";
337 };
337 };
338 };
338 };
339 zope.deprecation = super.buildPythonPackage {
339 zope.deprecation = super.buildPythonPackage {
340 name = "zope.deprecation-4.1.1";
340 name = "zope.deprecation-4.1.1";
341 buildInputs = with self; [];
341 buildInputs = with self; [];
342 doCheck = false;
342 doCheck = false;
343 propagatedBuildInputs = with self; [setuptools];
343 propagatedBuildInputs = with self; [setuptools];
344 src = fetchurl {
344 src = fetchurl {
345 url = "https://pypi.python.org/packages/c5/c9/e760f131fcde817da6c186a3f4952b8f206b7eeb269bb6f0836c715c5f20/zope.deprecation-4.1.1.tar.gz";
345 url = "https://pypi.python.org/packages/c5/c9/e760f131fcde817da6c186a3f4952b8f206b7eeb269bb6f0836c715c5f20/zope.deprecation-4.1.1.tar.gz";
346 md5 = "ce261b9384066f7e13b63525778430cb";
346 md5 = "ce261b9384066f7e13b63525778430cb";
347 };
347 };
348 };
348 };
349 zope.interface = super.buildPythonPackage {
349 zope.interface = super.buildPythonPackage {
350 name = "zope.interface-4.1.3";
350 name = "zope.interface-4.1.3";
351 buildInputs = with self; [];
351 buildInputs = with self; [];
352 doCheck = false;
352 doCheck = false;
353 propagatedBuildInputs = with self; [setuptools];
353 propagatedBuildInputs = with self; [setuptools];
354 src = fetchurl {
354 src = fetchurl {
355 url = "https://pypi.python.org/packages/9d/81/2509ca3c6f59080123c1a8a97125eb48414022618cec0e64eb1313727bfe/zope.interface-4.1.3.tar.gz";
355 url = "https://pypi.python.org/packages/9d/81/2509ca3c6f59080123c1a8a97125eb48414022618cec0e64eb1313727bfe/zope.interface-4.1.3.tar.gz";
356 md5 = "9ae3d24c0c7415deb249dd1a132f0f79";
356 md5 = "9ae3d24c0c7415deb249dd1a132f0f79";
357 };
357 };
358 };
358 };
359
359
360 ### Test requirements
360 ### Test requirements
361
361
362
362
363 }
363 }
@@ -1,13 +1,15 b''
1 { pkgs ? import <nixpkgs> {}
1 { pkgs ? import <nixpkgs> {}
2 , doCheck ? true
2 }:
3 }:
3
4
4 let
5 let
5
6
6 vcsserver = import ./default.nix {
7 vcsserver = import ./default.nix {
7 inherit
8 inherit
9 doCheck
8 pkgs;
10 pkgs;
9 };
11 };
10
12
11 in {
13 in {
12 build = vcsserver;
14 build = vcsserver;
13 }
15 }
@@ -1,34 +1,34 b''
1 Beaker==1.7.0
1 Beaker==1.7.0
2 configobj==5.0.6
2 configobj==5.0.6
3 dulwich==0.12.0
3 dulwich==0.13.0
4 hgsubversion==1.8.6
4 hgsubversion==1.8.6
5 infrae.cache==1.0.1
5 infrae.cache==1.0.1
6 mercurial==3.8.3
6 mercurial==3.8.3
7 msgpack-python==0.4.6
7 msgpack-python==0.4.6
8 py==1.4.29
8 py==1.4.29
9 pyramid==1.6.1
9 pyramid==1.6.1
10 pyramid-jinja2==2.5
10 pyramid-jinja2==2.5
11 pyramid-mako==1.0.2
11 pyramid-mako==1.0.2
12 Pyro4==4.41
12 Pyro4==4.41
13 pytest==2.8.5
13 pytest==2.8.5
14 repoze.lru==0.6
14 repoze.lru==0.6
15 serpent==1.12
15 serpent==1.12
16 setuptools==20.8.1
16 setuptools==20.8.1
17 simplejson==3.7.2
17 simplejson==3.7.2
18 subprocess32==3.2.6
18 subprocess32==3.2.6
19 # TODO: johbo: This version is not in source on PyPI currently,
19 # TODO: johbo: This version is not in source on PyPI currently,
20 # change back once this or a future version is available
20 # change back once this or a future version is available
21 https://github.com/jelmer/subvertpy/archive/subvertpy-0.9.3.tar.gz#md5=7b745a47128050ea5a73efcd913ec1cf
21 https://github.com/jelmer/subvertpy/archive/subvertpy-0.9.3.tar.gz#md5=7b745a47128050ea5a73efcd913ec1cf
22 six==1.9.0
22 six==1.9.0
23 translationstring==1.3
23 translationstring==1.3
24 waitress==0.8.9
24 waitress==0.8.9
25 WebOb==1.3.1
25 WebOb==1.3.1
26 wheel==0.29.0
26 wheel==0.29.0
27 zope.deprecation==4.1.1
27 zope.deprecation==4.1.1
28 zope.interface==4.1.3
28 zope.interface==4.1.3
29 greenlet==0.4.7
29 greenlet==0.4.7
30 gunicorn==19.6.0
30 gunicorn==19.6.0
31
31
32 # Test related requirements
32 # Test related requirements
33 mock==1.0.1
33 mock==1.0.1
34 WebTest==1.4.3
34 WebTest==1.4.3
@@ -1,13 +1,18 b''
1 { pkgs ? (import <nixpkgs> {})
1 { pkgs ? import <nixpkgs> {}
2 , doCheck ? false
2 }:
3 }:
3
4
4 let
5 let
5 vcsserver = import ./default.nix {inherit pkgs;};
6 vcsserver = import ./default.nix {
7 inherit
8 doCheck
9 pkgs;
10 };
6
11
7 in vcsserver.override (attrs: {
12 in vcsserver.override (attrs: {
8
13
9 # Avoid that we dump any sources into the store when entering the shell and
14 # Avoid that we dump any sources into the store when entering the shell and
10 # make development a little bit more convenient.
15 # make development a little bit more convenient.
11 src = null;
16 src = null;
12
17
13 })
18 })
@@ -1,1 +1,1 b''
1 4.1.2 No newline at end of file
1 4.2.0 No newline at end of file
@@ -1,692 +1,700 b''
1 # RhodeCode VCSServer provides access to different vcs backends via network.
1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 # Copyright (C) 2014-2016 RodeCode GmbH
2 # Copyright (C) 2014-2016 RodeCode GmbH
3 #
3 #
4 # This program is free software; you can redistribute it and/or modify
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
7 # (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
18 import io
18 import io
19 import logging
19 import logging
20 import stat
20 import stat
21 import sys
21 import sys
22 import urllib
22 import urllib
23 import urllib2
23 import urllib2
24
24
25 from hgext import largefiles, rebase
25 from hgext import largefiles, rebase
26 from hgext.strip import strip as hgext_strip
26 from hgext.strip import strip as hgext_strip
27 from mercurial import commands
27 from mercurial import commands
28 from mercurial import unionrepo
28 from mercurial import unionrepo
29
29
30 from vcsserver import exceptions
30 from vcsserver import exceptions
31 from vcsserver.base import RepoFactory
31 from vcsserver.base import RepoFactory
32 from vcsserver.hgcompat import (
32 from vcsserver.hgcompat import (
33 archival, bin, clone, config as hgconfig, diffopts, hex, hg_url,
33 archival, bin, clone, config as hgconfig, diffopts, hex, hg_url,
34 httpbasicauthhandler, httpdigestauthhandler, httppeer, localrepository,
34 httpbasicauthhandler, httpdigestauthhandler, httppeer, localrepository,
35 match, memctx, exchange, memfilectx, nullrev, patch, peer, revrange, ui,
35 match, memctx, exchange, memfilectx, nullrev, patch, peer, revrange, ui,
36 Abort, LookupError, RepoError, RepoLookupError, InterventionRequired,
36 Abort, LookupError, RepoError, RepoLookupError, InterventionRequired,
37 RequirementError)
37 RequirementError)
38
38
39 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
40
40
41
41
42 def make_ui_from_config(repo_config):
42 def make_ui_from_config(repo_config):
43 baseui = ui.ui()
43 baseui = ui.ui()
44
44
45 # clean the baseui object
45 # clean the baseui object
46 baseui._ocfg = hgconfig.config()
46 baseui._ocfg = hgconfig.config()
47 baseui._ucfg = hgconfig.config()
47 baseui._ucfg = hgconfig.config()
48 baseui._tcfg = hgconfig.config()
48 baseui._tcfg = hgconfig.config()
49
49
50 for section, option, value in repo_config:
50 for section, option, value in repo_config:
51 baseui.setconfig(section, option, value)
51 baseui.setconfig(section, option, value)
52
52
53 # make our hgweb quiet so it doesn't print output
53 # make our hgweb quiet so it doesn't print output
54 baseui.setconfig('ui', 'quiet', 'true')
54 baseui.setconfig('ui', 'quiet', 'true')
55
55
56 # force mercurial to only use 1 thread, otherwise it may try to set a
56 # force mercurial to only use 1 thread, otherwise it may try to set a
57 # signal in a non-main thread, thus generating a ValueError.
57 # signal in a non-main thread, thus generating a ValueError.
58 baseui.setconfig('worker', 'numcpus', 1)
58 baseui.setconfig('worker', 'numcpus', 1)
59
59
60 # If there is no config for the largefiles extension, we explicitly disable
61 # it here. This overrides settings from repositories hgrc file. Recent
62 # mercurial versions enable largefiles in hgrc on clone from largefile
63 # repo.
64 if not baseui.hasconfig('extensions', 'largefiles'):
65 log.debug('Explicitly disable largefiles extension for repo.')
66 baseui.setconfig('extensions', 'largefiles', '!')
67
60 return baseui
68 return baseui
61
69
62
70
63 def reraise_safe_exceptions(func):
71 def reraise_safe_exceptions(func):
64 """Decorator for converting mercurial exceptions to something neutral."""
72 """Decorator for converting mercurial exceptions to something neutral."""
65 def wrapper(*args, **kwargs):
73 def wrapper(*args, **kwargs):
66 try:
74 try:
67 return func(*args, **kwargs)
75 return func(*args, **kwargs)
68 except (Abort, InterventionRequired):
76 except (Abort, InterventionRequired):
69 raise_from_original(exceptions.AbortException)
77 raise_from_original(exceptions.AbortException)
70 except RepoLookupError:
78 except RepoLookupError:
71 raise_from_original(exceptions.LookupException)
79 raise_from_original(exceptions.LookupException)
72 except RequirementError:
80 except RequirementError:
73 raise_from_original(exceptions.RequirementException)
81 raise_from_original(exceptions.RequirementException)
74 except RepoError:
82 except RepoError:
75 raise_from_original(exceptions.VcsException)
83 raise_from_original(exceptions.VcsException)
76 except LookupError:
84 except LookupError:
77 raise_from_original(exceptions.LookupException)
85 raise_from_original(exceptions.LookupException)
78 except Exception as e:
86 except Exception as e:
79 if not hasattr(e, '_vcs_kind'):
87 if not hasattr(e, '_vcs_kind'):
80 log.exception("Unhandled exception in hg remote call")
88 log.exception("Unhandled exception in hg remote call")
81 raise_from_original(exceptions.UnhandledException)
89 raise_from_original(exceptions.UnhandledException)
82 raise
90 raise
83 return wrapper
91 return wrapper
84
92
85
93
86 def raise_from_original(new_type):
94 def raise_from_original(new_type):
87 """
95 """
88 Raise a new exception type with original args and traceback.
96 Raise a new exception type with original args and traceback.
89 """
97 """
90 _, original, traceback = sys.exc_info()
98 _, original, traceback = sys.exc_info()
91 try:
99 try:
92 raise new_type(*original.args), None, traceback
100 raise new_type(*original.args), None, traceback
93 finally:
101 finally:
94 del traceback
102 del traceback
95
103
96
104
97 class MercurialFactory(RepoFactory):
105 class MercurialFactory(RepoFactory):
98
106
99 def _create_config(self, config, hooks=True):
107 def _create_config(self, config, hooks=True):
100 if not hooks:
108 if not hooks:
101 hooks_to_clean = frozenset((
109 hooks_to_clean = frozenset((
102 'changegroup.repo_size', 'preoutgoing.pre_pull',
110 'changegroup.repo_size', 'preoutgoing.pre_pull',
103 'outgoing.pull_logger', 'prechangegroup.pre_push'))
111 'outgoing.pull_logger', 'prechangegroup.pre_push'))
104 new_config = []
112 new_config = []
105 for section, option, value in config:
113 for section, option, value in config:
106 if section == 'hooks' and option in hooks_to_clean:
114 if section == 'hooks' and option in hooks_to_clean:
107 continue
115 continue
108 new_config.append((section, option, value))
116 new_config.append((section, option, value))
109 config = new_config
117 config = new_config
110
118
111 baseui = make_ui_from_config(config)
119 baseui = make_ui_from_config(config)
112 return baseui
120 return baseui
113
121
114 def _create_repo(self, wire, create):
122 def _create_repo(self, wire, create):
115 baseui = self._create_config(wire["config"])
123 baseui = self._create_config(wire["config"])
116 return localrepository(baseui, wire["path"], create)
124 return localrepository(baseui, wire["path"], create)
117
125
118
126
119 class HgRemote(object):
127 class HgRemote(object):
120
128
121 def __init__(self, factory):
129 def __init__(self, factory):
122 self._factory = factory
130 self._factory = factory
123
131
124 self._bulk_methods = {
132 self._bulk_methods = {
125 "affected_files": self.ctx_files,
133 "affected_files": self.ctx_files,
126 "author": self.ctx_user,
134 "author": self.ctx_user,
127 "branch": self.ctx_branch,
135 "branch": self.ctx_branch,
128 "children": self.ctx_children,
136 "children": self.ctx_children,
129 "date": self.ctx_date,
137 "date": self.ctx_date,
130 "message": self.ctx_description,
138 "message": self.ctx_description,
131 "parents": self.ctx_parents,
139 "parents": self.ctx_parents,
132 "status": self.ctx_status,
140 "status": self.ctx_status,
133 "_file_paths": self.ctx_list,
141 "_file_paths": self.ctx_list,
134 }
142 }
135
143
136 @reraise_safe_exceptions
144 @reraise_safe_exceptions
137 def archive_repo(self, archive_path, mtime, file_info, kind):
145 def archive_repo(self, archive_path, mtime, file_info, kind):
138 if kind == "tgz":
146 if kind == "tgz":
139 archiver = archival.tarit(archive_path, mtime, "gz")
147 archiver = archival.tarit(archive_path, mtime, "gz")
140 elif kind == "tbz2":
148 elif kind == "tbz2":
141 archiver = archival.tarit(archive_path, mtime, "bz2")
149 archiver = archival.tarit(archive_path, mtime, "bz2")
142 elif kind == 'zip':
150 elif kind == 'zip':
143 archiver = archival.zipit(archive_path, mtime)
151 archiver = archival.zipit(archive_path, mtime)
144 else:
152 else:
145 raise exceptions.ArchiveException(
153 raise exceptions.ArchiveException(
146 'Remote does not support: "%s".' % kind)
154 'Remote does not support: "%s".' % kind)
147
155
148 for f_path, f_mode, f_is_link, f_content in file_info:
156 for f_path, f_mode, f_is_link, f_content in file_info:
149 archiver.addfile(f_path, f_mode, f_is_link, f_content)
157 archiver.addfile(f_path, f_mode, f_is_link, f_content)
150 archiver.done()
158 archiver.done()
151
159
152 @reraise_safe_exceptions
160 @reraise_safe_exceptions
153 def bookmarks(self, wire):
161 def bookmarks(self, wire):
154 repo = self._factory.repo(wire)
162 repo = self._factory.repo(wire)
155 return dict(repo._bookmarks)
163 return dict(repo._bookmarks)
156
164
157 @reraise_safe_exceptions
165 @reraise_safe_exceptions
158 def branches(self, wire, normal, closed):
166 def branches(self, wire, normal, closed):
159 repo = self._factory.repo(wire)
167 repo = self._factory.repo(wire)
160 iter_branches = repo.branchmap().iterbranches()
168 iter_branches = repo.branchmap().iterbranches()
161 bt = {}
169 bt = {}
162 for branch_name, _heads, tip, is_closed in iter_branches:
170 for branch_name, _heads, tip, is_closed in iter_branches:
163 if normal and not is_closed:
171 if normal and not is_closed:
164 bt[branch_name] = tip
172 bt[branch_name] = tip
165 if closed and is_closed:
173 if closed and is_closed:
166 bt[branch_name] = tip
174 bt[branch_name] = tip
167
175
168 return bt
176 return bt
169
177
170 @reraise_safe_exceptions
178 @reraise_safe_exceptions
171 def bulk_request(self, wire, rev, pre_load):
179 def bulk_request(self, wire, rev, pre_load):
172 result = {}
180 result = {}
173 for attr in pre_load:
181 for attr in pre_load:
174 try:
182 try:
175 method = self._bulk_methods[attr]
183 method = self._bulk_methods[attr]
176 result[attr] = method(wire, rev)
184 result[attr] = method(wire, rev)
177 except KeyError:
185 except KeyError:
178 raise exceptions.VcsException(
186 raise exceptions.VcsException(
179 'Unknown bulk attribute: "%s"' % attr)
187 'Unknown bulk attribute: "%s"' % attr)
180 return result
188 return result
181
189
182 @reraise_safe_exceptions
190 @reraise_safe_exceptions
183 def clone(self, wire, source, dest, update_after_clone=False, hooks=True):
191 def clone(self, wire, source, dest, update_after_clone=False, hooks=True):
184 baseui = self._factory._create_config(wire["config"], hooks=hooks)
192 baseui = self._factory._create_config(wire["config"], hooks=hooks)
185 clone(baseui, source, dest, noupdate=not update_after_clone)
193 clone(baseui, source, dest, noupdate=not update_after_clone)
186
194
187 @reraise_safe_exceptions
195 @reraise_safe_exceptions
188 def commitctx(
196 def commitctx(
189 self, wire, message, parents, commit_time, commit_timezone,
197 self, wire, message, parents, commit_time, commit_timezone,
190 user, files, extra, removed, updated):
198 user, files, extra, removed, updated):
191
199
192 def _filectxfn(_repo, memctx, path):
200 def _filectxfn(_repo, memctx, path):
193 """
201 """
194 Marks given path as added/changed/removed in a given _repo. This is
202 Marks given path as added/changed/removed in a given _repo. This is
195 for internal mercurial commit function.
203 for internal mercurial commit function.
196 """
204 """
197
205
198 # check if this path is removed
206 # check if this path is removed
199 if path in removed:
207 if path in removed:
200 # returning None is a way to mark node for removal
208 # returning None is a way to mark node for removal
201 return None
209 return None
202
210
203 # check if this path is added
211 # check if this path is added
204 for node in updated:
212 for node in updated:
205 if node['path'] == path:
213 if node['path'] == path:
206 return memfilectx(
214 return memfilectx(
207 _repo,
215 _repo,
208 path=node['path'],
216 path=node['path'],
209 data=node['content'],
217 data=node['content'],
210 islink=False,
218 islink=False,
211 isexec=bool(node['mode'] & stat.S_IXUSR),
219 isexec=bool(node['mode'] & stat.S_IXUSR),
212 copied=False,
220 copied=False,
213 memctx=memctx)
221 memctx=memctx)
214
222
215 raise exceptions.AbortException(
223 raise exceptions.AbortException(
216 "Given path haven't been marked as added, "
224 "Given path haven't been marked as added, "
217 "changed or removed (%s)" % path)
225 "changed or removed (%s)" % path)
218
226
219 repo = self._factory.repo(wire)
227 repo = self._factory.repo(wire)
220
228
221 commit_ctx = memctx(
229 commit_ctx = memctx(
222 repo=repo,
230 repo=repo,
223 parents=parents,
231 parents=parents,
224 text=message,
232 text=message,
225 files=files,
233 files=files,
226 filectxfn=_filectxfn,
234 filectxfn=_filectxfn,
227 user=user,
235 user=user,
228 date=(commit_time, commit_timezone),
236 date=(commit_time, commit_timezone),
229 extra=extra)
237 extra=extra)
230
238
231 n = repo.commitctx(commit_ctx)
239 n = repo.commitctx(commit_ctx)
232 new_id = hex(n)
240 new_id = hex(n)
233
241
234 return new_id
242 return new_id
235
243
236 @reraise_safe_exceptions
244 @reraise_safe_exceptions
237 def ctx_branch(self, wire, revision):
245 def ctx_branch(self, wire, revision):
238 repo = self._factory.repo(wire)
246 repo = self._factory.repo(wire)
239 ctx = repo[revision]
247 ctx = repo[revision]
240 return ctx.branch()
248 return ctx.branch()
241
249
242 @reraise_safe_exceptions
250 @reraise_safe_exceptions
243 def ctx_children(self, wire, revision):
251 def ctx_children(self, wire, revision):
244 repo = self._factory.repo(wire)
252 repo = self._factory.repo(wire)
245 ctx = repo[revision]
253 ctx = repo[revision]
246 return [child.rev() for child in ctx.children()]
254 return [child.rev() for child in ctx.children()]
247
255
248 @reraise_safe_exceptions
256 @reraise_safe_exceptions
249 def ctx_date(self, wire, revision):
257 def ctx_date(self, wire, revision):
250 repo = self._factory.repo(wire)
258 repo = self._factory.repo(wire)
251 ctx = repo[revision]
259 ctx = repo[revision]
252 return ctx.date()
260 return ctx.date()
253
261
254 @reraise_safe_exceptions
262 @reraise_safe_exceptions
255 def ctx_description(self, wire, revision):
263 def ctx_description(self, wire, revision):
256 repo = self._factory.repo(wire)
264 repo = self._factory.repo(wire)
257 ctx = repo[revision]
265 ctx = repo[revision]
258 return ctx.description()
266 return ctx.description()
259
267
260 @reraise_safe_exceptions
268 @reraise_safe_exceptions
261 def ctx_diff(
269 def ctx_diff(
262 self, wire, revision, git=True, ignore_whitespace=True, context=3):
270 self, wire, revision, git=True, ignore_whitespace=True, context=3):
263 repo = self._factory.repo(wire)
271 repo = self._factory.repo(wire)
264 ctx = repo[revision]
272 ctx = repo[revision]
265 result = ctx.diff(
273 result = ctx.diff(
266 git=git, ignore_whitespace=ignore_whitespace, context=context)
274 git=git, ignore_whitespace=ignore_whitespace, context=context)
267 return list(result)
275 return list(result)
268
276
269 @reraise_safe_exceptions
277 @reraise_safe_exceptions
270 def ctx_files(self, wire, revision):
278 def ctx_files(self, wire, revision):
271 repo = self._factory.repo(wire)
279 repo = self._factory.repo(wire)
272 ctx = repo[revision]
280 ctx = repo[revision]
273 return ctx.files()
281 return ctx.files()
274
282
275 @reraise_safe_exceptions
283 @reraise_safe_exceptions
276 def ctx_list(self, path, revision):
284 def ctx_list(self, path, revision):
277 repo = self._factory.repo(path)
285 repo = self._factory.repo(path)
278 ctx = repo[revision]
286 ctx = repo[revision]
279 return list(ctx)
287 return list(ctx)
280
288
281 @reraise_safe_exceptions
289 @reraise_safe_exceptions
282 def ctx_parents(self, wire, revision):
290 def ctx_parents(self, wire, revision):
283 repo = self._factory.repo(wire)
291 repo = self._factory.repo(wire)
284 ctx = repo[revision]
292 ctx = repo[revision]
285 return [parent.rev() for parent in ctx.parents()]
293 return [parent.rev() for parent in ctx.parents()]
286
294
287 @reraise_safe_exceptions
295 @reraise_safe_exceptions
288 def ctx_substate(self, wire, revision):
296 def ctx_substate(self, wire, revision):
289 repo = self._factory.repo(wire)
297 repo = self._factory.repo(wire)
290 ctx = repo[revision]
298 ctx = repo[revision]
291 return ctx.substate
299 return ctx.substate
292
300
293 @reraise_safe_exceptions
301 @reraise_safe_exceptions
294 def ctx_status(self, wire, revision):
302 def ctx_status(self, wire, revision):
295 repo = self._factory.repo(wire)
303 repo = self._factory.repo(wire)
296 ctx = repo[revision]
304 ctx = repo[revision]
297 status = repo[ctx.p1().node()].status(other=ctx.node())
305 status = repo[ctx.p1().node()].status(other=ctx.node())
298 # object of status (odd, custom named tuple in mercurial) is not
306 # object of status (odd, custom named tuple in mercurial) is not
299 # correctly serializable via Pyro, we make it a list, as the underling
307 # correctly serializable via Pyro, we make it a list, as the underling
300 # API expects this to be a list
308 # API expects this to be a list
301 return list(status)
309 return list(status)
302
310
303 @reraise_safe_exceptions
311 @reraise_safe_exceptions
304 def ctx_user(self, wire, revision):
312 def ctx_user(self, wire, revision):
305 repo = self._factory.repo(wire)
313 repo = self._factory.repo(wire)
306 ctx = repo[revision]
314 ctx = repo[revision]
307 return ctx.user()
315 return ctx.user()
308
316
309 @reraise_safe_exceptions
317 @reraise_safe_exceptions
310 def check_url(self, url, config):
318 def check_url(self, url, config):
311 _proto = None
319 _proto = None
312 if '+' in url[:url.find('://')]:
320 if '+' in url[:url.find('://')]:
313 _proto = url[0:url.find('+')]
321 _proto = url[0:url.find('+')]
314 url = url[url.find('+') + 1:]
322 url = url[url.find('+') + 1:]
315 handlers = []
323 handlers = []
316 url_obj = hg_url(url)
324 url_obj = hg_url(url)
317 test_uri, authinfo = url_obj.authinfo()
325 test_uri, authinfo = url_obj.authinfo()
318 url_obj.passwd = '*****'
326 url_obj.passwd = '*****'
319 cleaned_uri = str(url_obj)
327 cleaned_uri = str(url_obj)
320
328
321 if authinfo:
329 if authinfo:
322 # create a password manager
330 # create a password manager
323 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
331 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
324 passmgr.add_password(*authinfo)
332 passmgr.add_password(*authinfo)
325
333
326 handlers.extend((httpbasicauthhandler(passmgr),
334 handlers.extend((httpbasicauthhandler(passmgr),
327 httpdigestauthhandler(passmgr)))
335 httpdigestauthhandler(passmgr)))
328
336
329 o = urllib2.build_opener(*handlers)
337 o = urllib2.build_opener(*handlers)
330 o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
338 o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
331 ('Accept', 'application/mercurial-0.1')]
339 ('Accept', 'application/mercurial-0.1')]
332
340
333 q = {"cmd": 'between'}
341 q = {"cmd": 'between'}
334 q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)})
342 q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)})
335 qs = '?%s' % urllib.urlencode(q)
343 qs = '?%s' % urllib.urlencode(q)
336 cu = "%s%s" % (test_uri, qs)
344 cu = "%s%s" % (test_uri, qs)
337 req = urllib2.Request(cu, None, {})
345 req = urllib2.Request(cu, None, {})
338
346
339 try:
347 try:
340 resp = o.open(req)
348 resp = o.open(req)
341 if resp.code != 200:
349 if resp.code != 200:
342 raise exceptions.URLError('Return Code is not 200')
350 raise exceptions.URLError('Return Code is not 200')
343 except Exception as e:
351 except Exception as e:
344 # means it cannot be cloned
352 # means it cannot be cloned
345 raise exceptions.URLError("[%s] org_exc: %s" % (cleaned_uri, e))
353 raise exceptions.URLError("[%s] org_exc: %s" % (cleaned_uri, e))
346
354
347 # now check if it's a proper hg repo, but don't do it for svn
355 # now check if it's a proper hg repo, but don't do it for svn
348 try:
356 try:
349 if _proto == 'svn':
357 if _proto == 'svn':
350 pass
358 pass
351 else:
359 else:
352 # check for pure hg repos
360 # check for pure hg repos
353 httppeer(make_ui_from_config(config), url).lookup('tip')
361 httppeer(make_ui_from_config(config), url).lookup('tip')
354 except Exception as e:
362 except Exception as e:
355 raise exceptions.URLError(
363 raise exceptions.URLError(
356 "url [%s] does not look like an hg repo org_exc: %s"
364 "url [%s] does not look like an hg repo org_exc: %s"
357 % (cleaned_uri, e))
365 % (cleaned_uri, e))
358
366
359 return True
367 return True
360
368
361 @reraise_safe_exceptions
369 @reraise_safe_exceptions
362 def diff(
370 def diff(
363 self, wire, rev1, rev2, file_filter, opt_git, opt_ignorews,
371 self, wire, rev1, rev2, file_filter, opt_git, opt_ignorews,
364 context):
372 context):
365 repo = self._factory.repo(wire)
373 repo = self._factory.repo(wire)
366
374
367 if file_filter:
375 if file_filter:
368 filter = match(file_filter[0], '', [file_filter[1]])
376 filter = match(file_filter[0], '', [file_filter[1]])
369 else:
377 else:
370 filter = file_filter
378 filter = file_filter
371 opts = diffopts(git=opt_git, ignorews=opt_ignorews, context=context)
379 opts = diffopts(git=opt_git, ignorews=opt_ignorews, context=context)
372
380
373 try:
381 try:
374 return "".join(patch.diff(
382 return "".join(patch.diff(
375 repo, node1=rev1, node2=rev2, match=filter, opts=opts))
383 repo, node1=rev1, node2=rev2, match=filter, opts=opts))
376 except RepoLookupError:
384 except RepoLookupError:
377 raise exceptions.LookupException()
385 raise exceptions.LookupException()
378
386
379 @reraise_safe_exceptions
387 @reraise_safe_exceptions
380 def file_history(self, wire, revision, path, limit):
388 def file_history(self, wire, revision, path, limit):
381 repo = self._factory.repo(wire)
389 repo = self._factory.repo(wire)
382
390
383 ctx = repo[revision]
391 ctx = repo[revision]
384 fctx = ctx.filectx(path)
392 fctx = ctx.filectx(path)
385
393
386 def history_iter():
394 def history_iter():
387 limit_rev = fctx.rev()
395 limit_rev = fctx.rev()
388 for obj in reversed(list(fctx.filelog())):
396 for obj in reversed(list(fctx.filelog())):
389 obj = fctx.filectx(obj)
397 obj = fctx.filectx(obj)
390 if limit_rev >= obj.rev():
398 if limit_rev >= obj.rev():
391 yield obj
399 yield obj
392
400
393 history = []
401 history = []
394 for cnt, obj in enumerate(history_iter()):
402 for cnt, obj in enumerate(history_iter()):
395 if limit and cnt >= limit:
403 if limit and cnt >= limit:
396 break
404 break
397 history.append(hex(obj.node()))
405 history.append(hex(obj.node()))
398
406
399 return [x for x in history]
407 return [x for x in history]
400
408
401 @reraise_safe_exceptions
409 @reraise_safe_exceptions
402 def file_history_untill(self, wire, revision, path, limit):
410 def file_history_untill(self, wire, revision, path, limit):
403 repo = self._factory.repo(wire)
411 repo = self._factory.repo(wire)
404 ctx = repo[revision]
412 ctx = repo[revision]
405 fctx = ctx.filectx(path)
413 fctx = ctx.filectx(path)
406
414
407 file_log = list(fctx.filelog())
415 file_log = list(fctx.filelog())
408 if limit:
416 if limit:
409 # Limit to the last n items
417 # Limit to the last n items
410 file_log = file_log[-limit:]
418 file_log = file_log[-limit:]
411
419
412 return [hex(fctx.filectx(cs).node()) for cs in reversed(file_log)]
420 return [hex(fctx.filectx(cs).node()) for cs in reversed(file_log)]
413
421
414 @reraise_safe_exceptions
422 @reraise_safe_exceptions
415 def fctx_annotate(self, wire, revision, path):
423 def fctx_annotate(self, wire, revision, path):
416 repo = self._factory.repo(wire)
424 repo = self._factory.repo(wire)
417 ctx = repo[revision]
425 ctx = repo[revision]
418 fctx = ctx.filectx(path)
426 fctx = ctx.filectx(path)
419
427
420 result = []
428 result = []
421 for i, annotate_data in enumerate(fctx.annotate()):
429 for i, annotate_data in enumerate(fctx.annotate()):
422 ln_no = i + 1
430 ln_no = i + 1
423 sha = hex(annotate_data[0].node())
431 sha = hex(annotate_data[0].node())
424 result.append((ln_no, sha, annotate_data[1]))
432 result.append((ln_no, sha, annotate_data[1]))
425 return result
433 return result
426
434
427 @reraise_safe_exceptions
435 @reraise_safe_exceptions
428 def fctx_data(self, wire, revision, path):
436 def fctx_data(self, wire, revision, path):
429 repo = self._factory.repo(wire)
437 repo = self._factory.repo(wire)
430 ctx = repo[revision]
438 ctx = repo[revision]
431 fctx = ctx.filectx(path)
439 fctx = ctx.filectx(path)
432 return fctx.data()
440 return fctx.data()
433
441
434 @reraise_safe_exceptions
442 @reraise_safe_exceptions
435 def fctx_flags(self, wire, revision, path):
443 def fctx_flags(self, wire, revision, path):
436 repo = self._factory.repo(wire)
444 repo = self._factory.repo(wire)
437 ctx = repo[revision]
445 ctx = repo[revision]
438 fctx = ctx.filectx(path)
446 fctx = ctx.filectx(path)
439 return fctx.flags()
447 return fctx.flags()
440
448
441 @reraise_safe_exceptions
449 @reraise_safe_exceptions
442 def fctx_size(self, wire, revision, path):
450 def fctx_size(self, wire, revision, path):
443 repo = self._factory.repo(wire)
451 repo = self._factory.repo(wire)
444 ctx = repo[revision]
452 ctx = repo[revision]
445 fctx = ctx.filectx(path)
453 fctx = ctx.filectx(path)
446 return fctx.size()
454 return fctx.size()
447
455
448 @reraise_safe_exceptions
456 @reraise_safe_exceptions
449 def get_all_commit_ids(self, wire, name):
457 def get_all_commit_ids(self, wire, name):
450 repo = self._factory.repo(wire)
458 repo = self._factory.repo(wire)
451 revs = repo.filtered(name).changelog.index
459 revs = repo.filtered(name).changelog.index
452 return map(lambda x: hex(x[7]), revs)[:-1]
460 return map(lambda x: hex(x[7]), revs)[:-1]
453
461
454 @reraise_safe_exceptions
462 @reraise_safe_exceptions
455 def get_config_value(self, wire, section, name, untrusted=False):
463 def get_config_value(self, wire, section, name, untrusted=False):
456 repo = self._factory.repo(wire)
464 repo = self._factory.repo(wire)
457 return repo.ui.config(section, name, untrusted=untrusted)
465 return repo.ui.config(section, name, untrusted=untrusted)
458
466
459 @reraise_safe_exceptions
467 @reraise_safe_exceptions
460 def get_config_bool(self, wire, section, name, untrusted=False):
468 def get_config_bool(self, wire, section, name, untrusted=False):
461 repo = self._factory.repo(wire)
469 repo = self._factory.repo(wire)
462 return repo.ui.configbool(section, name, untrusted=untrusted)
470 return repo.ui.configbool(section, name, untrusted=untrusted)
463
471
464 @reraise_safe_exceptions
472 @reraise_safe_exceptions
465 def get_config_list(self, wire, section, name, untrusted=False):
473 def get_config_list(self, wire, section, name, untrusted=False):
466 repo = self._factory.repo(wire)
474 repo = self._factory.repo(wire)
467 return repo.ui.configlist(section, name, untrusted=untrusted)
475 return repo.ui.configlist(section, name, untrusted=untrusted)
468
476
469 @reraise_safe_exceptions
477 @reraise_safe_exceptions
470 def is_large_file(self, wire, path):
478 def is_large_file(self, wire, path):
471 return largefiles.lfutil.isstandin(path)
479 return largefiles.lfutil.isstandin(path)
472
480
473 @reraise_safe_exceptions
481 @reraise_safe_exceptions
474 def in_store(self, wire, sha):
482 def in_store(self, wire, sha):
475 repo = self._factory.repo(wire)
483 repo = self._factory.repo(wire)
476 return largefiles.lfutil.instore(repo, sha)
484 return largefiles.lfutil.instore(repo, sha)
477
485
478 @reraise_safe_exceptions
486 @reraise_safe_exceptions
479 def in_user_cache(self, wire, sha):
487 def in_user_cache(self, wire, sha):
480 repo = self._factory.repo(wire)
488 repo = self._factory.repo(wire)
481 return largefiles.lfutil.inusercache(repo.ui, sha)
489 return largefiles.lfutil.inusercache(repo.ui, sha)
482
490
483 @reraise_safe_exceptions
491 @reraise_safe_exceptions
484 def store_path(self, wire, sha):
492 def store_path(self, wire, sha):
485 repo = self._factory.repo(wire)
493 repo = self._factory.repo(wire)
486 return largefiles.lfutil.storepath(repo, sha)
494 return largefiles.lfutil.storepath(repo, sha)
487
495
488 @reraise_safe_exceptions
496 @reraise_safe_exceptions
489 def link(self, wire, sha, path):
497 def link(self, wire, sha, path):
490 repo = self._factory.repo(wire)
498 repo = self._factory.repo(wire)
491 largefiles.lfutil.link(
499 largefiles.lfutil.link(
492 largefiles.lfutil.usercachepath(repo.ui, sha), path)
500 largefiles.lfutil.usercachepath(repo.ui, sha), path)
493
501
494 @reraise_safe_exceptions
502 @reraise_safe_exceptions
495 def localrepository(self, wire, create=False):
503 def localrepository(self, wire, create=False):
496 self._factory.repo(wire, create=create)
504 self._factory.repo(wire, create=create)
497
505
498 @reraise_safe_exceptions
506 @reraise_safe_exceptions
499 def lookup(self, wire, revision, both):
507 def lookup(self, wire, revision, both):
500 # TODO Paris: Ugly hack to "deserialize" long for msgpack
508 # TODO Paris: Ugly hack to "deserialize" long for msgpack
501 if isinstance(revision, float):
509 if isinstance(revision, float):
502 revision = long(revision)
510 revision = long(revision)
503 repo = self._factory.repo(wire)
511 repo = self._factory.repo(wire)
504 try:
512 try:
505 ctx = repo[revision]
513 ctx = repo[revision]
506 except RepoLookupError:
514 except RepoLookupError:
507 raise exceptions.LookupException(revision)
515 raise exceptions.LookupException(revision)
508 except LookupError as e:
516 except LookupError as e:
509 raise exceptions.LookupException(e.name)
517 raise exceptions.LookupException(e.name)
510
518
511 if not both:
519 if not both:
512 return ctx.hex()
520 return ctx.hex()
513
521
514 ctx = repo[ctx.hex()]
522 ctx = repo[ctx.hex()]
515 return ctx.hex(), ctx.rev()
523 return ctx.hex(), ctx.rev()
516
524
517 @reraise_safe_exceptions
525 @reraise_safe_exceptions
518 def pull(self, wire, url, commit_ids=None):
526 def pull(self, wire, url, commit_ids=None):
519 repo = self._factory.repo(wire)
527 repo = self._factory.repo(wire)
520 remote = peer(repo, {}, url)
528 remote = peer(repo, {}, url)
521 if commit_ids:
529 if commit_ids:
522 commit_ids = [bin(commit_id) for commit_id in commit_ids]
530 commit_ids = [bin(commit_id) for commit_id in commit_ids]
523
531
524 return exchange.pull(
532 return exchange.pull(
525 repo, remote, heads=commit_ids, force=None).cgresult
533 repo, remote, heads=commit_ids, force=None).cgresult
526
534
527 @reraise_safe_exceptions
535 @reraise_safe_exceptions
528 def revision(self, wire, rev):
536 def revision(self, wire, rev):
529 repo = self._factory.repo(wire)
537 repo = self._factory.repo(wire)
530 ctx = repo[rev]
538 ctx = repo[rev]
531 return ctx.rev()
539 return ctx.rev()
532
540
533 @reraise_safe_exceptions
541 @reraise_safe_exceptions
534 def rev_range(self, wire, filter):
542 def rev_range(self, wire, filter):
535 repo = self._factory.repo(wire)
543 repo = self._factory.repo(wire)
536 revisions = [rev for rev in revrange(repo, filter)]
544 revisions = [rev for rev in revrange(repo, filter)]
537 return revisions
545 return revisions
538
546
539 @reraise_safe_exceptions
547 @reraise_safe_exceptions
540 def rev_range_hash(self, wire, node):
548 def rev_range_hash(self, wire, node):
541 repo = self._factory.repo(wire)
549 repo = self._factory.repo(wire)
542
550
543 def get_revs(repo, rev_opt):
551 def get_revs(repo, rev_opt):
544 if rev_opt:
552 if rev_opt:
545 revs = revrange(repo, rev_opt)
553 revs = revrange(repo, rev_opt)
546 if len(revs) == 0:
554 if len(revs) == 0:
547 return (nullrev, nullrev)
555 return (nullrev, nullrev)
548 return max(revs), min(revs)
556 return max(revs), min(revs)
549 else:
557 else:
550 return len(repo) - 1, 0
558 return len(repo) - 1, 0
551
559
552 stop, start = get_revs(repo, [node + ':'])
560 stop, start = get_revs(repo, [node + ':'])
553 revs = [hex(repo[r].node()) for r in xrange(start, stop + 1)]
561 revs = [hex(repo[r].node()) for r in xrange(start, stop + 1)]
554 return revs
562 return revs
555
563
556 @reraise_safe_exceptions
564 @reraise_safe_exceptions
557 def revs_from_revspec(self, wire, rev_spec, *args, **kwargs):
565 def revs_from_revspec(self, wire, rev_spec, *args, **kwargs):
558 other_path = kwargs.pop('other_path', None)
566 other_path = kwargs.pop('other_path', None)
559
567
560 # case when we want to compare two independent repositories
568 # case when we want to compare two independent repositories
561 if other_path and other_path != wire["path"]:
569 if other_path and other_path != wire["path"]:
562 baseui = self._factory._create_config(wire["config"])
570 baseui = self._factory._create_config(wire["config"])
563 repo = unionrepo.unionrepository(baseui, other_path, wire["path"])
571 repo = unionrepo.unionrepository(baseui, other_path, wire["path"])
564 else:
572 else:
565 repo = self._factory.repo(wire)
573 repo = self._factory.repo(wire)
566 return list(repo.revs(rev_spec, *args))
574 return list(repo.revs(rev_spec, *args))
567
575
568 @reraise_safe_exceptions
576 @reraise_safe_exceptions
569 def strip(self, wire, revision, update, backup):
577 def strip(self, wire, revision, update, backup):
570 repo = self._factory.repo(wire)
578 repo = self._factory.repo(wire)
571 ctx = repo[revision]
579 ctx = repo[revision]
572 hgext_strip(
580 hgext_strip(
573 repo.baseui, repo, ctx.node(), update=update, backup=backup)
581 repo.baseui, repo, ctx.node(), update=update, backup=backup)
574
582
575 @reraise_safe_exceptions
583 @reraise_safe_exceptions
576 def tag(self, wire, name, revision, message, local, user,
584 def tag(self, wire, name, revision, message, local, user,
577 tag_time, tag_timezone):
585 tag_time, tag_timezone):
578 repo = self._factory.repo(wire)
586 repo = self._factory.repo(wire)
579 ctx = repo[revision]
587 ctx = repo[revision]
580 node = ctx.node()
588 node = ctx.node()
581
589
582 date = (tag_time, tag_timezone)
590 date = (tag_time, tag_timezone)
583 try:
591 try:
584 repo.tag(name, node, message, local, user, date)
592 repo.tag(name, node, message, local, user, date)
585 except Abort:
593 except Abort:
586 log.exception("Tag operation aborted")
594 log.exception("Tag operation aborted")
587 raise exceptions.AbortException()
595 raise exceptions.AbortException()
588
596
589 @reraise_safe_exceptions
597 @reraise_safe_exceptions
590 def tags(self, wire):
598 def tags(self, wire):
591 repo = self._factory.repo(wire)
599 repo = self._factory.repo(wire)
592 return repo.tags()
600 return repo.tags()
593
601
594 @reraise_safe_exceptions
602 @reraise_safe_exceptions
595 def update(self, wire, node=None, clean=False):
603 def update(self, wire, node=None, clean=False):
596 repo = self._factory.repo(wire)
604 repo = self._factory.repo(wire)
597 baseui = self._factory._create_config(wire['config'])
605 baseui = self._factory._create_config(wire['config'])
598 commands.update(baseui, repo, node=node, clean=clean)
606 commands.update(baseui, repo, node=node, clean=clean)
599
607
600 @reraise_safe_exceptions
608 @reraise_safe_exceptions
601 def identify(self, wire):
609 def identify(self, wire):
602 repo = self._factory.repo(wire)
610 repo = self._factory.repo(wire)
603 baseui = self._factory._create_config(wire['config'])
611 baseui = self._factory._create_config(wire['config'])
604 output = io.BytesIO()
612 output = io.BytesIO()
605 baseui.write = output.write
613 baseui.write = output.write
606 # This is required to get a full node id
614 # This is required to get a full node id
607 baseui.debugflag = True
615 baseui.debugflag = True
608 commands.identify(baseui, repo, id=True)
616 commands.identify(baseui, repo, id=True)
609
617
610 return output.getvalue()
618 return output.getvalue()
611
619
612 @reraise_safe_exceptions
620 @reraise_safe_exceptions
613 def pull_cmd(self, wire, source, bookmark=None, branch=None, revision=None,
621 def pull_cmd(self, wire, source, bookmark=None, branch=None, revision=None,
614 hooks=True):
622 hooks=True):
615 repo = self._factory.repo(wire)
623 repo = self._factory.repo(wire)
616 baseui = self._factory._create_config(wire['config'], hooks=hooks)
624 baseui = self._factory._create_config(wire['config'], hooks=hooks)
617
625
618 # Mercurial internally has a lot of logic that checks ONLY if
626 # Mercurial internally has a lot of logic that checks ONLY if
619 # option is defined, we just pass those if they are defined then
627 # option is defined, we just pass those if they are defined then
620 opts = {}
628 opts = {}
621 if bookmark:
629 if bookmark:
622 opts['bookmark'] = bookmark
630 opts['bookmark'] = bookmark
623 if branch:
631 if branch:
624 opts['branch'] = branch
632 opts['branch'] = branch
625 if revision:
633 if revision:
626 opts['rev'] = revision
634 opts['rev'] = revision
627
635
628 commands.pull(baseui, repo, source, **opts)
636 commands.pull(baseui, repo, source, **opts)
629
637
630 @reraise_safe_exceptions
638 @reraise_safe_exceptions
631 def heads(self, wire, branch=None):
639 def heads(self, wire, branch=None):
632 repo = self._factory.repo(wire)
640 repo = self._factory.repo(wire)
633 baseui = self._factory._create_config(wire['config'])
641 baseui = self._factory._create_config(wire['config'])
634 output = io.BytesIO()
642 output = io.BytesIO()
635
643
636 def write(data, **unused_kwargs):
644 def write(data, **unused_kwargs):
637 output.write(data)
645 output.write(data)
638
646
639 baseui.write = write
647 baseui.write = write
640 if branch:
648 if branch:
641 args = [branch]
649 args = [branch]
642 else:
650 else:
643 args = []
651 args = []
644 commands.heads(baseui, repo, template='{node} ', *args)
652 commands.heads(baseui, repo, template='{node} ', *args)
645
653
646 return output.getvalue()
654 return output.getvalue()
647
655
648 @reraise_safe_exceptions
656 @reraise_safe_exceptions
649 def ancestor(self, wire, revision1, revision2):
657 def ancestor(self, wire, revision1, revision2):
650 repo = self._factory.repo(wire)
658 repo = self._factory.repo(wire)
651 baseui = self._factory._create_config(wire['config'])
659 baseui = self._factory._create_config(wire['config'])
652 output = io.BytesIO()
660 output = io.BytesIO()
653 baseui.write = output.write
661 baseui.write = output.write
654 commands.debugancestor(baseui, repo, revision1, revision2)
662 commands.debugancestor(baseui, repo, revision1, revision2)
655
663
656 return output.getvalue()
664 return output.getvalue()
657
665
658 @reraise_safe_exceptions
666 @reraise_safe_exceptions
659 def push(self, wire, revisions, dest_path, hooks=True,
667 def push(self, wire, revisions, dest_path, hooks=True,
660 push_branches=False):
668 push_branches=False):
661 repo = self._factory.repo(wire)
669 repo = self._factory.repo(wire)
662 baseui = self._factory._create_config(wire['config'], hooks=hooks)
670 baseui = self._factory._create_config(wire['config'], hooks=hooks)
663 commands.push(baseui, repo, dest=dest_path, rev=revisions,
671 commands.push(baseui, repo, dest=dest_path, rev=revisions,
664 new_branch=push_branches)
672 new_branch=push_branches)
665
673
666 @reraise_safe_exceptions
674 @reraise_safe_exceptions
667 def merge(self, wire, revision):
675 def merge(self, wire, revision):
668 repo = self._factory.repo(wire)
676 repo = self._factory.repo(wire)
669 baseui = self._factory._create_config(wire['config'])
677 baseui = self._factory._create_config(wire['config'])
670 repo.ui.setconfig('ui', 'merge', 'internal:dump')
678 repo.ui.setconfig('ui', 'merge', 'internal:dump')
671 commands.merge(baseui, repo, rev=revision)
679 commands.merge(baseui, repo, rev=revision)
672
680
673 @reraise_safe_exceptions
681 @reraise_safe_exceptions
674 def commit(self, wire, message, username):
682 def commit(self, wire, message, username):
675 repo = self._factory.repo(wire)
683 repo = self._factory.repo(wire)
676 baseui = self._factory._create_config(wire['config'])
684 baseui = self._factory._create_config(wire['config'])
677 repo.ui.setconfig('ui', 'username', username)
685 repo.ui.setconfig('ui', 'username', username)
678 commands.commit(baseui, repo, message=message)
686 commands.commit(baseui, repo, message=message)
679
687
680 @reraise_safe_exceptions
688 @reraise_safe_exceptions
681 def rebase(self, wire, source=None, dest=None, abort=False):
689 def rebase(self, wire, source=None, dest=None, abort=False):
682 repo = self._factory.repo(wire)
690 repo = self._factory.repo(wire)
683 baseui = self._factory._create_config(wire['config'])
691 baseui = self._factory._create_config(wire['config'])
684 repo.ui.setconfig('ui', 'merge', 'internal:dump')
692 repo.ui.setconfig('ui', 'merge', 'internal:dump')
685 rebase.rebase(
693 rebase.rebase(
686 baseui, repo, base=source, dest=dest, abort=abort, keep=not abort)
694 baseui, repo, base=source, dest=dest, abort=abort, keep=not abort)
687
695
688 @reraise_safe_exceptions
696 @reraise_safe_exceptions
689 def bookmark(self, wire, bookmark, revision=None):
697 def bookmark(self, wire, bookmark, revision=None):
690 repo = self._factory.repo(wire)
698 repo = self._factory.repo(wire)
691 baseui = self._factory._create_config(wire['config'])
699 baseui = self._factory._create_config(wire['config'])
692 commands.bookmark(baseui, repo, bookmark, rev=revision, force=True)
700 commands.bookmark(baseui, repo, bookmark, rev=revision, force=True)
@@ -1,335 +1,337 b''
1 # RhodeCode VCSServer provides access to different vcs backends via network.
1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 # Copyright (C) 2014-2016 RodeCode GmbH
2 # Copyright (C) 2014-2016 RodeCode GmbH
3 #
3 #
4 # This program is free software; you can redistribute it and/or modify
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
7 # (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
18 import base64
18 import base64
19 import locale
19 import locale
20 import logging
20 import logging
21 import uuid
21 import uuid
22 import wsgiref.util
22 import wsgiref.util
23 from itertools import chain
23 from itertools import chain
24
24
25 import msgpack
25 import msgpack
26 from beaker.cache import CacheManager
26 from beaker.cache import CacheManager
27 from beaker.util import parse_cache_config_options
27 from beaker.util import parse_cache_config_options
28 from pyramid.config import Configurator
28 from pyramid.config import Configurator
29 from pyramid.wsgi import wsgiapp
29 from pyramid.wsgi import wsgiapp
30
30
31 from vcsserver import remote_wsgi, scm_app, settings
31 from vcsserver import remote_wsgi, scm_app, settings, hgpatches
32 from vcsserver.echo_stub import remote_wsgi as remote_wsgi_stub
32 from vcsserver.echo_stub import remote_wsgi as remote_wsgi_stub
33 from vcsserver.echo_stub.echo_app import EchoApp
33 from vcsserver.echo_stub.echo_app import EchoApp
34 from vcsserver.server import VcsServer
34 from vcsserver.server import VcsServer
35
35
36 try:
36 try:
37 from vcsserver.git import GitFactory, GitRemote
37 from vcsserver.git import GitFactory, GitRemote
38 except ImportError:
38 except ImportError:
39 GitFactory = None
39 GitFactory = None
40 GitRemote = None
40 GitRemote = None
41 try:
41 try:
42 from vcsserver.hg import MercurialFactory, HgRemote
42 from vcsserver.hg import MercurialFactory, HgRemote
43 except ImportError:
43 except ImportError:
44 MercurialFactory = None
44 MercurialFactory = None
45 HgRemote = None
45 HgRemote = None
46 try:
46 try:
47 from vcsserver.svn import SubversionFactory, SvnRemote
47 from vcsserver.svn import SubversionFactory, SvnRemote
48 except ImportError:
48 except ImportError:
49 SubversionFactory = None
49 SubversionFactory = None
50 SvnRemote = None
50 SvnRemote = None
51
51
52 log = logging.getLogger(__name__)
52 log = logging.getLogger(__name__)
53
53
54
54
55 class VCS(object):
55 class VCS(object):
56 def __init__(self, locale=None, cache_config=None):
56 def __init__(self, locale=None, cache_config=None):
57 self.locale = locale
57 self.locale = locale
58 self.cache_config = cache_config
58 self.cache_config = cache_config
59 self._configure_locale()
59 self._configure_locale()
60 self._initialize_cache()
60 self._initialize_cache()
61
61
62 if GitFactory and GitRemote:
62 if GitFactory and GitRemote:
63 git_repo_cache = self.cache.get_cache_region(
63 git_repo_cache = self.cache.get_cache_region(
64 'git', region='repo_object')
64 'git', region='repo_object')
65 git_factory = GitFactory(git_repo_cache)
65 git_factory = GitFactory(git_repo_cache)
66 self._git_remote = GitRemote(git_factory)
66 self._git_remote = GitRemote(git_factory)
67 else:
67 else:
68 log.info("Git client import failed")
68 log.info("Git client import failed")
69
69
70 if MercurialFactory and HgRemote:
70 if MercurialFactory and HgRemote:
71 hg_repo_cache = self.cache.get_cache_region(
71 hg_repo_cache = self.cache.get_cache_region(
72 'hg', region='repo_object')
72 'hg', region='repo_object')
73 hg_factory = MercurialFactory(hg_repo_cache)
73 hg_factory = MercurialFactory(hg_repo_cache)
74 self._hg_remote = HgRemote(hg_factory)
74 self._hg_remote = HgRemote(hg_factory)
75 else:
75 else:
76 log.info("Mercurial client import failed")
76 log.info("Mercurial client import failed")
77
77
78 if SubversionFactory and SvnRemote:
78 if SubversionFactory and SvnRemote:
79 svn_repo_cache = self.cache.get_cache_region(
79 svn_repo_cache = self.cache.get_cache_region(
80 'svn', region='repo_object')
80 'svn', region='repo_object')
81 svn_factory = SubversionFactory(svn_repo_cache)
81 svn_factory = SubversionFactory(svn_repo_cache)
82 self._svn_remote = SvnRemote(svn_factory, hg_factory=hg_factory)
82 self._svn_remote = SvnRemote(svn_factory, hg_factory=hg_factory)
83 else:
83 else:
84 log.info("Subversion client import failed")
84 log.info("Subversion client import failed")
85
85
86 self._vcsserver = VcsServer()
86 self._vcsserver = VcsServer()
87
87
88 def _initialize_cache(self):
88 def _initialize_cache(self):
89 cache_config = parse_cache_config_options(self.cache_config)
89 cache_config = parse_cache_config_options(self.cache_config)
90 log.info('Initializing beaker cache: %s' % cache_config)
90 log.info('Initializing beaker cache: %s' % cache_config)
91 self.cache = CacheManager(**cache_config)
91 self.cache = CacheManager(**cache_config)
92
92
93 def _configure_locale(self):
93 def _configure_locale(self):
94 if self.locale:
94 if self.locale:
95 log.info('Settings locale: `LC_ALL` to %s' % self.locale)
95 log.info('Settings locale: `LC_ALL` to %s' % self.locale)
96 else:
96 else:
97 log.info(
97 log.info(
98 'Configuring locale subsystem based on environment variables')
98 'Configuring locale subsystem based on environment variables')
99 try:
99 try:
100 # If self.locale is the empty string, then the locale
100 # If self.locale is the empty string, then the locale
101 # module will use the environment variables. See the
101 # module will use the environment variables. See the
102 # documentation of the package `locale`.
102 # documentation of the package `locale`.
103 locale.setlocale(locale.LC_ALL, self.locale)
103 locale.setlocale(locale.LC_ALL, self.locale)
104
104
105 language_code, encoding = locale.getlocale()
105 language_code, encoding = locale.getlocale()
106 log.info(
106 log.info(
107 'Locale set to language code "%s" with encoding "%s".',
107 'Locale set to language code "%s" with encoding "%s".',
108 language_code, encoding)
108 language_code, encoding)
109 except locale.Error:
109 except locale.Error:
110 log.exception(
110 log.exception(
111 'Cannot set locale, not configuring the locale system')
111 'Cannot set locale, not configuring the locale system')
112
112
113
113
114 class WsgiProxy(object):
114 class WsgiProxy(object):
115 def __init__(self, wsgi):
115 def __init__(self, wsgi):
116 self.wsgi = wsgi
116 self.wsgi = wsgi
117
117
118 def __call__(self, environ, start_response):
118 def __call__(self, environ, start_response):
119 input_data = environ['wsgi.input'].read()
119 input_data = environ['wsgi.input'].read()
120 input_data = msgpack.unpackb(input_data)
120 input_data = msgpack.unpackb(input_data)
121
121
122 error = None
122 error = None
123 try:
123 try:
124 data, status, headers = self.wsgi.handle(
124 data, status, headers = self.wsgi.handle(
125 input_data['environment'], input_data['input_data'],
125 input_data['environment'], input_data['input_data'],
126 *input_data['args'], **input_data['kwargs'])
126 *input_data['args'], **input_data['kwargs'])
127 except Exception as e:
127 except Exception as e:
128 data, status, headers = [], None, None
128 data, status, headers = [], None, None
129 error = {
129 error = {
130 'message': str(e),
130 'message': str(e),
131 '_vcs_kind': getattr(e, '_vcs_kind', None)
131 '_vcs_kind': getattr(e, '_vcs_kind', None)
132 }
132 }
133
133
134 start_response(200, {})
134 start_response(200, {})
135 return self._iterator(error, status, headers, data)
135 return self._iterator(error, status, headers, data)
136
136
137 def _iterator(self, error, status, headers, data):
137 def _iterator(self, error, status, headers, data):
138 initial_data = [
138 initial_data = [
139 error,
139 error,
140 status,
140 status,
141 headers,
141 headers,
142 ]
142 ]
143
143
144 for d in chain(initial_data, data):
144 for d in chain(initial_data, data):
145 yield msgpack.packb(d)
145 yield msgpack.packb(d)
146
146
147
147
148 class HTTPApplication(object):
148 class HTTPApplication(object):
149 ALLOWED_EXCEPTIONS = ('KeyError', 'URLError')
149 ALLOWED_EXCEPTIONS = ('KeyError', 'URLError')
150
150
151 remote_wsgi = remote_wsgi
151 remote_wsgi = remote_wsgi
152 _use_echo_app = False
152 _use_echo_app = False
153
153
154 def __init__(self, settings=None):
154 def __init__(self, settings=None):
155 self.config = Configurator(settings=settings)
155 self.config = Configurator(settings=settings)
156 locale = settings.get('', 'en_US.UTF-8')
156 locale = settings.get('', 'en_US.UTF-8')
157 vcs = VCS(locale=locale, cache_config=settings)
157 vcs = VCS(locale=locale, cache_config=settings)
158 self._remotes = {
158 self._remotes = {
159 'hg': vcs._hg_remote,
159 'hg': vcs._hg_remote,
160 'git': vcs._git_remote,
160 'git': vcs._git_remote,
161 'svn': vcs._svn_remote,
161 'svn': vcs._svn_remote,
162 'server': vcs._vcsserver,
162 'server': vcs._vcsserver,
163 }
163 }
164 if settings.get('dev.use_echo_app', 'false').lower() == 'true':
164 if settings.get('dev.use_echo_app', 'false').lower() == 'true':
165 self._use_echo_app = True
165 self._use_echo_app = True
166 log.warning("Using EchoApp for VCS operations.")
166 log.warning("Using EchoApp for VCS operations.")
167 self.remote_wsgi = remote_wsgi_stub
167 self.remote_wsgi = remote_wsgi_stub
168 self._configure_settings(settings)
168 self._configure_settings(settings)
169 self._configure()
169 self._configure()
170
170
171 def _configure_settings(self, app_settings):
171 def _configure_settings(self, app_settings):
172 """
172 """
173 Configure the settings module.
173 Configure the settings module.
174 """
174 """
175 git_path = app_settings.get('git_path', None)
175 git_path = app_settings.get('git_path', None)
176 if git_path:
176 if git_path:
177 settings.GIT_EXECUTABLE = git_path
177 settings.GIT_EXECUTABLE = git_path
178
178
179 def _configure(self):
179 def _configure(self):
180 self.config.add_renderer(
180 self.config.add_renderer(
181 name='msgpack',
181 name='msgpack',
182 factory=self._msgpack_renderer_factory)
182 factory=self._msgpack_renderer_factory)
183
183
184 self.config.add_route('status', '/status')
184 self.config.add_route('status', '/status')
185 self.config.add_route('hg_proxy', '/proxy/hg')
185 self.config.add_route('hg_proxy', '/proxy/hg')
186 self.config.add_route('git_proxy', '/proxy/git')
186 self.config.add_route('git_proxy', '/proxy/git')
187 self.config.add_route('vcs', '/{backend}')
187 self.config.add_route('vcs', '/{backend}')
188 self.config.add_route('stream_git', '/stream/git/*repo_name')
188 self.config.add_route('stream_git', '/stream/git/*repo_name')
189 self.config.add_route('stream_hg', '/stream/hg/*repo_name')
189 self.config.add_route('stream_hg', '/stream/hg/*repo_name')
190
190
191 self.config.add_view(
191 self.config.add_view(
192 self.status_view, route_name='status', renderer='json')
192 self.status_view, route_name='status', renderer='json')
193 self.config.add_view(self.hg_proxy(), route_name='hg_proxy')
193 self.config.add_view(self.hg_proxy(), route_name='hg_proxy')
194 self.config.add_view(self.git_proxy(), route_name='git_proxy')
194 self.config.add_view(self.git_proxy(), route_name='git_proxy')
195 self.config.add_view(
195 self.config.add_view(
196 self.vcs_view, route_name='vcs', renderer='msgpack')
196 self.vcs_view, route_name='vcs', renderer='msgpack')
197
197
198 self.config.add_view(self.hg_stream(), route_name='stream_hg')
198 self.config.add_view(self.hg_stream(), route_name='stream_hg')
199 self.config.add_view(self.git_stream(), route_name='stream_git')
199 self.config.add_view(self.git_stream(), route_name='stream_git')
200
200
201 def wsgi_app(self):
201 def wsgi_app(self):
202 return self.config.make_wsgi_app()
202 return self.config.make_wsgi_app()
203
203
204 def vcs_view(self, request):
204 def vcs_view(self, request):
205 remote = self._remotes[request.matchdict['backend']]
205 remote = self._remotes[request.matchdict['backend']]
206 payload = msgpack.unpackb(request.body, use_list=True)
206 payload = msgpack.unpackb(request.body, use_list=True)
207 method = payload.get('method')
207 method = payload.get('method')
208 params = payload.get('params')
208 params = payload.get('params')
209 wire = params.get('wire')
209 wire = params.get('wire')
210 args = params.get('args')
210 args = params.get('args')
211 kwargs = params.get('kwargs')
211 kwargs = params.get('kwargs')
212 if wire:
212 if wire:
213 try:
213 try:
214 wire['context'] = uuid.UUID(wire['context'])
214 wire['context'] = uuid.UUID(wire['context'])
215 except KeyError:
215 except KeyError:
216 pass
216 pass
217 args.insert(0, wire)
217 args.insert(0, wire)
218
218
219 try:
219 try:
220 resp = getattr(remote, method)(*args, **kwargs)
220 resp = getattr(remote, method)(*args, **kwargs)
221 except Exception as e:
221 except Exception as e:
222 type_ = e.__class__.__name__
222 type_ = e.__class__.__name__
223 if type_ not in self.ALLOWED_EXCEPTIONS:
223 if type_ not in self.ALLOWED_EXCEPTIONS:
224 type_ = None
224 type_ = None
225
225
226 resp = {
226 resp = {
227 'id': payload.get('id'),
227 'id': payload.get('id'),
228 'error': {
228 'error': {
229 'message': e.message,
229 'message': e.message,
230 'type': type_
230 'type': type_
231 }
231 }
232 }
232 }
233 try:
233 try:
234 resp['error']['_vcs_kind'] = e._vcs_kind
234 resp['error']['_vcs_kind'] = e._vcs_kind
235 except AttributeError:
235 except AttributeError:
236 pass
236 pass
237 else:
237 else:
238 resp = {
238 resp = {
239 'id': payload.get('id'),
239 'id': payload.get('id'),
240 'result': resp
240 'result': resp
241 }
241 }
242
242
243 return resp
243 return resp
244
244
245 def status_view(self, request):
245 def status_view(self, request):
246 return {'status': 'OK'}
246 return {'status': 'OK'}
247
247
248 def _msgpack_renderer_factory(self, info):
248 def _msgpack_renderer_factory(self, info):
249 def _render(value, system):
249 def _render(value, system):
250 value = msgpack.packb(value)
250 value = msgpack.packb(value)
251 request = system.get('request')
251 request = system.get('request')
252 if request is not None:
252 if request is not None:
253 response = request.response
253 response = request.response
254 ct = response.content_type
254 ct = response.content_type
255 if ct == response.default_content_type:
255 if ct == response.default_content_type:
256 response.content_type = 'application/x-msgpack'
256 response.content_type = 'application/x-msgpack'
257 return value
257 return value
258 return _render
258 return _render
259
259
260 def hg_proxy(self):
260 def hg_proxy(self):
261 @wsgiapp
261 @wsgiapp
262 def _hg_proxy(environ, start_response):
262 def _hg_proxy(environ, start_response):
263 app = WsgiProxy(self.remote_wsgi.HgRemoteWsgi())
263 app = WsgiProxy(self.remote_wsgi.HgRemoteWsgi())
264 return app(environ, start_response)
264 return app(environ, start_response)
265 return _hg_proxy
265 return _hg_proxy
266
266
267 def git_proxy(self):
267 def git_proxy(self):
268 @wsgiapp
268 @wsgiapp
269 def _git_proxy(environ, start_response):
269 def _git_proxy(environ, start_response):
270 app = WsgiProxy(self.remote_wsgi.GitRemoteWsgi())
270 app = WsgiProxy(self.remote_wsgi.GitRemoteWsgi())
271 return app(environ, start_response)
271 return app(environ, start_response)
272 return _git_proxy
272 return _git_proxy
273
273
274 def hg_stream(self):
274 def hg_stream(self):
275 if self._use_echo_app:
275 if self._use_echo_app:
276 @wsgiapp
276 @wsgiapp
277 def _hg_stream(environ, start_response):
277 def _hg_stream(environ, start_response):
278 app = EchoApp('fake_path', 'fake_name', None)
278 app = EchoApp('fake_path', 'fake_name', None)
279 return app(environ, start_response)
279 return app(environ, start_response)
280 return _hg_stream
280 return _hg_stream
281 else:
281 else:
282 @wsgiapp
282 @wsgiapp
283 def _hg_stream(environ, start_response):
283 def _hg_stream(environ, start_response):
284 repo_path = environ['HTTP_X_RC_REPO_PATH']
284 repo_path = environ['HTTP_X_RC_REPO_PATH']
285 repo_name = environ['HTTP_X_RC_REPO_NAME']
285 repo_name = environ['HTTP_X_RC_REPO_NAME']
286 packed_config = base64.b64decode(
286 packed_config = base64.b64decode(
287 environ['HTTP_X_RC_REPO_CONFIG'])
287 environ['HTTP_X_RC_REPO_CONFIG'])
288 config = msgpack.unpackb(packed_config)
288 config = msgpack.unpackb(packed_config)
289 app = scm_app.create_hg_wsgi_app(
289 app = scm_app.create_hg_wsgi_app(
290 repo_path, repo_name, config)
290 repo_path, repo_name, config)
291
291
292 # Consitent path information for hgweb
292 # Consitent path information for hgweb
293 environ['PATH_INFO'] = environ['HTTP_X_RC_PATH_INFO']
293 environ['PATH_INFO'] = environ['HTTP_X_RC_PATH_INFO']
294 environ['REPO_NAME'] = repo_name
294 environ['REPO_NAME'] = repo_name
295 return app(environ, ResponseFilter(start_response))
295 return app(environ, ResponseFilter(start_response))
296 return _hg_stream
296 return _hg_stream
297
297
298 def git_stream(self):
298 def git_stream(self):
299 if self._use_echo_app:
299 if self._use_echo_app:
300 @wsgiapp
300 @wsgiapp
301 def _git_stream(environ, start_response):
301 def _git_stream(environ, start_response):
302 app = EchoApp('fake_path', 'fake_name', None)
302 app = EchoApp('fake_path', 'fake_name', None)
303 return app(environ, start_response)
303 return app(environ, start_response)
304 return _git_stream
304 return _git_stream
305 else:
305 else:
306 @wsgiapp
306 @wsgiapp
307 def _git_stream(environ, start_response):
307 def _git_stream(environ, start_response):
308 repo_path = environ['HTTP_X_RC_REPO_PATH']
308 repo_path = environ['HTTP_X_RC_REPO_PATH']
309 repo_name = environ['HTTP_X_RC_REPO_NAME']
309 repo_name = environ['HTTP_X_RC_REPO_NAME']
310 packed_config = base64.b64decode(
310 packed_config = base64.b64decode(
311 environ['HTTP_X_RC_REPO_CONFIG'])
311 environ['HTTP_X_RC_REPO_CONFIG'])
312 config = msgpack.unpackb(packed_config)
312 config = msgpack.unpackb(packed_config)
313
313
314 environ['PATH_INFO'] = environ['HTTP_X_RC_PATH_INFO']
314 environ['PATH_INFO'] = environ['HTTP_X_RC_PATH_INFO']
315 app = scm_app.create_git_wsgi_app(
315 app = scm_app.create_git_wsgi_app(
316 repo_path, repo_name, config)
316 repo_path, repo_name, config)
317 return app(environ, start_response)
317 return app(environ, start_response)
318 return _git_stream
318 return _git_stream
319
319
320
320
321 class ResponseFilter(object):
321 class ResponseFilter(object):
322
322
323 def __init__(self, start_response):
323 def __init__(self, start_response):
324 self._start_response = start_response
324 self._start_response = start_response
325
325
326 def __call__(self, status, response_headers, exc_info=None):
326 def __call__(self, status, response_headers, exc_info=None):
327 headers = tuple(
327 headers = tuple(
328 (h, v) for h, v in response_headers
328 (h, v) for h, v in response_headers
329 if not wsgiref.util.is_hop_by_hop(h))
329 if not wsgiref.util.is_hop_by_hop(h))
330 return self._start_response(status, headers, exc_info)
330 return self._start_response(status, headers, exc_info)
331
331
332
332
333 def main(global_config, **settings):
333 def main(global_config, **settings):
334 if MercurialFactory:
335 hgpatches.patch_largefiles_capabilities()
334 app = HTTPApplication(settings=settings)
336 app = HTTPApplication(settings=settings)
335 return app.wsgi_app()
337 return app.wsgi_app()
General Comments 0
You need to be logged in to leave comments. Login now