2 from functools
import partial
4 from qtpy
import QtCore
5 from qtpy
import QtWidgets
6 from qtpy
.QtCore
import Qt
12 from .. import qtutils
14 from ..interaction
import Interaction
15 from ..qtutils
import get
17 from . import standard
21 def clone(context
, spawn
=True, show
=True):
22 """Clone a repository and spawn a new git-cola instance"""
23 parent
= qtutils
.active_window()
24 progress
= standard
.progress('', '', parent
)
25 return clone_repo(context
, show
, progress
, task_finished
, spawn
)
28 def clone_repo(context
, show
, progress
, finish
, spawn
):
29 """Clone a repository asynchronously with progress animation"""
30 func
= partial(start_clone_task
, context
, progress
, finish
, spawn
)
31 prompt
= prompt_for_clone(context
, show
=show
)
32 prompt
.result
.connect(func
)
36 def prompt_for_clone(context
, show
=True):
37 """Presents a GUI for cloning a repository"""
38 view
= Clone(context
, parent
=qtutils
.active_window())
44 def task_finished(task
):
45 """Report errors from the clone task if they exist"""
52 title
= N_('Error: could not clone "%s"') % cmd
.url
53 Interaction
.command(title
, 'git clone', status
, out
, err
)
57 context
, progress
, finish
, spawn
, url
, destdir
, submodules
, shallow
59 # Use a thread to update in the background
60 runtask
= context
.runtask
61 progress
.set_details(N_('Clone Repository'), N_('Cloning repository at %s') % url
)
62 task
= CloneTask(context
, url
, destdir
, submodules
, shallow
, spawn
)
63 runtask
.start(task
, finish
=finish
, progress
=progress
)
66 class CloneTask(qtutils
.Task
):
67 """Clones a Git repository"""
69 def __init__(self
, context
, url
, destdir
, submodules
, shallow
, spawn
):
70 qtutils
.Task
.__init
__(self
)
71 self
.context
= context
73 self
.destdir
= destdir
74 self
.submodules
= submodules
75 self
.shallow
= shallow
80 """Runs the model action and captures the result"""
93 class Clone(standard
.Dialog
):
94 # Signal binding for returning the input data
95 result
= QtCore
.Signal(object, object, bool, bool)
97 def __init__(self
, context
, parent
=None):
98 standard
.Dialog
.__init
__(self
, parent
=parent
)
99 self
.context
= context
100 self
.model
= context
.model
102 self
.setWindowTitle(N_('Clone Repository'))
103 if parent
is not None:
104 self
.setWindowModality(Qt
.WindowModal
)
106 # Repository location
107 self
.url_label
= QtWidgets
.QLabel(N_('URL'))
108 hint
= 'git://git.example.com/repo.git'
109 self
.url
= text
.HintedLineEdit(context
, hint
, parent
=self
)
110 self
.url
.setToolTip(N_('Path or URL to clone (Env. $VARS okay)'))
112 # Initialize submodules
113 self
.submodules
= qtutils
.checkbox(
114 text
=N_('Inititalize submodules'), checked
=False
117 # Reduce commit history
118 self
.shallow
= qtutils
.checkbox(
119 text
=N_('Reduce commit history to minimum'), checked
=False
123 self
.ok_button
= qtutils
.create_button(
124 text
=N_('Clone'), icon
=icons
.ok(), default
=True
126 self
.close_button
= qtutils
.close_button()
128 # Form layout for inputs
129 self
.input_layout
= qtutils
.form(
130 defs
.no_margin
, defs
.button_spacing
, (self
.url_label
, self
.url
)
133 self
.button_layout
= qtutils
.hbox(
144 self
.main_layout
= qtutils
.vbox(
145 defs
.margin
, defs
.spacing
, self
.input_layout
, self
.button_layout
147 self
.setLayout(self
.main_layout
)
149 qtutils
.connect_button(self
.close_button
, self
.close
)
150 qtutils
.connect_button(self
.ok_button
, self
.prepare_to_clone
)
151 # pylint: disable=no-member
152 self
.url
.textChanged
.connect(lambda x
: self
.update_actions())
154 self
.init_state(context
.settings
, self
.resize
, 720, 200)
155 self
.update_actions()
157 def update_actions(self
):
158 url
= get(self
.url
).strip()
160 self
.ok_button
.setEnabled(enabled
)
162 def prepare_to_clone(self
):
163 """Grabs and validates the input data"""
165 submodules
= get(self
.submodules
)
166 shallow
= get(self
.shallow
)
169 url
= utils
.expandpath(url
)
172 # Pick a suitable basename by parsing the URL
173 newurl
= url
.replace('\\', '/').rstrip('/')
175 default
= newurl
.rsplit('/', 1)[-1]
178 if default
== '.git':
179 # The end of the URL is /.git, so assume it's a file path
180 default
= os
.path
.basename(os
.path
.dirname(newurl
))
181 if default
.endswith('.git'):
182 # The URL points to a bare repo
183 default
= default
[:-4]
185 # The URL is the current repo
186 default
= os
.path
.basename(core
.getcwd())
188 Interaction
.information(
189 N_('Error Cloning'), N_('Could not parse Git URL: "%s"') % url
191 Interaction
.log(N_('Could not parse Git URL: "%s"') % url
)
194 # Prompt the user for a directory to use as the parent directory
195 msg
= N_('Select a parent directory for the new clone')
196 dirname
= qtutils
.opendir_dialog(msg
, self
.model
.getcwd())
200 destdir
= os
.path
.join(dirname
, default
)
202 if core
.exists(destdir
):
203 # An existing path can be specified
204 msg
= N_('"%s" already exists, cola will create a new directory') % destdir
205 Interaction
.information(N_('Directory Exists'), msg
)
207 # Make sure the directory doesn't exist
208 while core
.exists(destdir
):
209 destdir
= olddestdir
+ str(count
)
212 # Return the input data and close the dialog
213 self
.result
.emit(url
, destdir
, submodules
, shallow
)