4
4
import os
5
5
import re
6
6
import shutil
7
+ import site
7
8
import stat
8
9
import subprocess
9
10
import sys
16
17
from cleo import option
17
18
18
19
from poetry .core .packages import Dependency
20
+ from poetry .utils ._compat import PY2
21
+ from poetry .utils ._compat import Path
19
22
20
23
from ..command import Command
21
24
@@ -60,6 +63,10 @@ class SelfUpdateCommand(Command):
60
63
REPOSITORY_URL = "https://github.com/python-poetry/poetry"
61
64
BASE_URL = REPOSITORY_URL + "/releases/download"
62
65
66
+ _data_dir = None
67
+ _bin_dir = None
68
+ _pool = None
69
+
63
70
@property
64
71
def home (self ):
65
72
from poetry .utils ._compat import Path
@@ -78,18 +85,75 @@ def lib(self):
78
85
def lib_backup (self ):
79
86
return self .home / "lib-backup"
80
87
88
+ @property
89
+ def data_dir (self ): # type: () -> Path
90
+ if self ._data_dir is not None :
91
+ return self ._data_dir
92
+
93
+ from poetry .locations import data_dir
94
+
95
+ self ._data_dir = data_dir ()
96
+
97
+ return self ._data_dir
98
+
99
+ @property
100
+ def bin_dir (self ): # type: () -> Path
101
+ if self ._data_dir is not None :
102
+ return self ._data_dir
103
+
104
+ from poetry .utils ._compat import WINDOWS
105
+
106
+ if os .getenv ("POETRY_HOME" ):
107
+ return Path (os .getenv ("POETRY_HOME" ), "bin" ).expanduser ()
108
+
109
+ user_base = site .getuserbase ()
110
+
111
+ if WINDOWS :
112
+ bin_dir = os .path .join (user_base , "Scripts" )
113
+ else :
114
+ bin_dir = os .path .join (user_base , "bin" )
115
+
116
+ self ._bin_dir = Path (bin_dir )
117
+
118
+ return self ._bin_dir
119
+
120
+ @property
121
+ def pool (self ):
122
+ if self ._pool is not None :
123
+ return self ._pool
124
+
125
+ from poetry .repositories .pool import Pool
126
+ from poetry .repositories .pypi_repository import PyPiRepository
127
+
128
+ pool = Pool ()
129
+ pool .add_repository (PyPiRepository (fallback = False ))
130
+
131
+ self ._pool = pool
132
+
133
+ return self ._pool
134
+
81
135
def handle (self ):
82
136
from poetry .__version__ import __version__
83
137
from poetry .core .semver import Version
84
- from poetry .repositories .pypi_repository import PyPiRepository
138
+ from poetry .utils .env import EnvManager
139
+
140
+ new_update_method = False
141
+ try :
142
+ self ._check_recommended_installation ()
143
+ except RuntimeError as e :
144
+ env = EnvManager .get_system_env (naive = True )
145
+ try :
146
+ env .path .relative_to (self .data_dir )
147
+ except ValueError :
148
+ raise e
85
149
86
- self . _check_recommended_installation ()
150
+ new_update_method = True
87
151
88
152
version = self .argument ("version" )
89
153
if not version :
90
154
version = ">=" + __version__
91
155
92
- repo = PyPiRepository ( fallback = False )
156
+ repo = self . pool . repositories [ 0 ]
93
157
packages = repo .find_packages (
94
158
Dependency ("poetry" , version , allows_prereleases = self .option ("preview" ))
95
159
)
@@ -127,6 +191,9 @@ def handle(self):
127
191
self .line ("You are using the latest version" )
128
192
return
129
193
194
+ if new_update_method :
195
+ return self .update_with_new_method (release .version )
196
+
130
197
self .update (release )
131
198
132
199
def update (self , release ):
@@ -165,6 +232,18 @@ def update(self, release):
165
232
)
166
233
)
167
234
235
+ def update_with_new_method (self , version ):
236
+ self .line ("Updating <c1>Poetry</c1> to <c2>{}</c2>" .format (version ))
237
+ self .line ("" )
238
+
239
+ self ._update_with_new_method (version )
240
+ self ._make_bin ()
241
+
242
+ self .line ("" )
243
+ self .line (
244
+ "<c1>Poetry</c1> (<c2>{}</c2>) is installed now. Great!" .format (version )
245
+ )
246
+
168
247
def _update (self , version ):
169
248
from poetry .utils .helpers import temporary_directory
170
249
@@ -235,6 +314,68 @@ def _update(self, version):
235
314
finally :
236
315
gz .close ()
237
316
317
+ def _update_with_new_method (self , version ):
318
+ from poetry .config .config import Config
319
+ from poetry .core .packages .dependency import Dependency
320
+ from poetry .core .packages .project_package import ProjectPackage
321
+ from poetry .installation .installer import Installer
322
+ from poetry .packages .locker import NullLocker
323
+ from poetry .repositories .installed_repository import InstalledRepository
324
+ from poetry .utils .env import EnvManager
325
+
326
+ env = EnvManager .get_system_env ()
327
+ installed = InstalledRepository .load (env )
328
+
329
+ root = ProjectPackage ("poetry-updater" , "0.0.0" )
330
+ root .python_versions = "." .join (str (c ) for c in env .version_info [:3 ])
331
+ root .add_dependency (Dependency ("poetry" , version .text ))
332
+
333
+ installer = Installer (
334
+ self .io ,
335
+ env ,
336
+ root ,
337
+ NullLocker (self .data_dir .joinpath ("poetry.lock" ), {}),
338
+ self .pool ,
339
+ Config (),
340
+ installed = installed ,
341
+ )
342
+ installer .update (True )
343
+ installer .run ()
344
+
345
+ def _make_bin (self ):
346
+ from poetry .utils ._compat import WINDOWS
347
+
348
+ self .line ("" )
349
+ self .line ("Updating the <c1>poetry</c1> script" )
350
+
351
+ self .bin_dir .mkdir (parents = True , exist_ok = True )
352
+
353
+ script = "poetry"
354
+ target_script = "venv/bin/poetry"
355
+ if WINDOWS :
356
+ script = "poetry.exe"
357
+ target_script = "venv/Scripts/poetry.exe"
358
+
359
+ if self .bin_dir .joinpath (script ).exists ():
360
+ self .bin_dir .joinpath (script ).unlink ()
361
+
362
+ if not PY2 and not WINDOWS :
363
+ try :
364
+ self .bin_dir .joinpath (script ).symlink_to (
365
+ self .data_dir .joinpath (target_script )
366
+ )
367
+ except OSError :
368
+ # This can happen if the user
369
+ # does not have the correct permission on Windows
370
+ shutil .copy (
371
+ self .data_dir .joinpath (target_script ), self .bin_dir .joinpath (script )
372
+ )
373
+ else :
374
+ shutil .copy (
375
+ str (self .data_dir .joinpath (target_script )),
376
+ str (self .bin_dir .joinpath (script )),
377
+ )
378
+
238
379
def process (self , * args ):
239
380
return subprocess .check_output (list (args ), stderr = subprocess .STDOUT )
240
381
0 commit comments