@@ -132,8 +132,8 @@ def _split_by_type(self, changes: Dict[str, List[dict]]) -> List[Dict[str, List[
132
132
1. Blocking: updated/removed and added files that are blocking
133
133
2. Non-blocking: added files that are not blocking
134
134
"""
135
- blocking_changes = {"added" : [], "updated" : [], "removed" : [], "renamed" : [] }
136
- non_blocking_changes = {"added" : [], "updated" : [], "removed" : [], "renamed" : [] }
135
+ blocking_changes = {"added" : [], "updated" : [], "removed" : []}
136
+ non_blocking_changes = {"added" : [], "updated" : [], "removed" : []}
137
137
138
138
for f in changes .get ("added" , []):
139
139
if self .is_blocking_file (f ):
@@ -164,18 +164,26 @@ def split(self) -> List[Dict[str, List[dict]]]:
164
164
# TODO: apply limits; changes = self._limit_by_file_count(changes)
165
165
return changes_list
166
166
167
- def get_change_batch (self ) -> Tuple [Optional [Dict [str , List [dict ]]], bool ]:
168
- """
169
- Return the next changes dictionary and flag if there are more changes
170
- """
171
- changes_list = self .split ()
172
- if not changes_list :
173
- return None , False
174
- return changes_list [0 ], len (changes_list ) > 1
167
+ def get_change_batch (mc , project_dir ) -> Tuple [Optional [Dict [str , List [dict ]]], bool ]:
168
+ """
169
+ Return the next changes dictionary and flag if there are more changes (to be uploaded in the next upload job)
170
+ """
171
+ changes_list = ChangesHandler (mc , project_dir ).split ()
172
+ if not changes_list :
173
+ return None , False
174
+ non_empty_length = sum (any (v for v in d .values ()) for d in changes_list )
175
+ return changes_list [0 ], non_empty_length > 1
175
176
176
177
177
178
def push_project_async (mc , directory , change_batch = None ) -> Optional [UploadJob ]:
178
- """Starts push of a change of a project and returns pending upload job"""
179
+ """
180
+ Starts push in background and returns pending upload job.
181
+ Pushes all project changes unless change_batch is provided.
182
+ When specific change is provided, initial version check is skipped (the pull has just been done).
183
+
184
+ :param change_batch: A dictionary of changes that was split to blocking and non-blocking.
185
+ Pushing only non-blocking changes results in non-exclusive upload which server allows to be concurrent.
186
+ """
179
187
180
188
mp = MerginProject (directory )
181
189
if mp .has_unfinished_pull ():
@@ -187,30 +195,32 @@ def push_project_async(mc, directory, change_batch=None) -> Optional[UploadJob]:
187
195
mp .log .info ("--- version: " + mc .user_agent_info ())
188
196
mp .log .info (f"--- start push { project_path } " )
189
197
190
- try :
191
- project_info = mc .project_info (project_path )
192
- except ClientError as err :
193
- mp .log .error ("Error getting project info: " + str (err ))
194
- mp .log .info ("--- push aborted" )
195
- raise
196
- server_version = project_info ["version" ] if project_info ["version" ] else "v0"
197
-
198
- mp .log .info (f"got project info: local version { local_version } / server version { server_version } " )
199
-
200
- username = mc .username ()
201
- # permissions field contains information about update, delete and upload privileges of the user
202
- # on a specific project. This is more accurate information than "writernames" field, as it takes
203
- # into account namespace privileges. So we have to check only "permissions", namely "upload" once
204
- if not mc .has_writing_permissions (project_path ):
205
- mp .log .error (f"--- push { project_path } - username { username } does not have write access" )
206
- raise ClientError (f"You do not seem to have write access to the project (username '{ username } ')" )
207
-
208
- if local_version != server_version :
209
- mp .log .error (f"--- push { project_path } - not up to date (local { local_version } vs server { server_version } )" )
210
- raise ClientError (
211
- "There is a new version of the project on the server. Please update your local copy."
212
- + f"\n \n Local version: { local_version } \n Server version: { server_version } "
213
- )
198
+ # if we have specific change to push we don't need version check
199
+ if not change_batch :
200
+ try :
201
+ project_info = mc .project_info (project_path )
202
+ except ClientError as err :
203
+ mp .log .error ("Error getting project info: " + str (err ))
204
+ mp .log .info ("--- push aborted" )
205
+ raise
206
+ server_version = project_info ["version" ] if project_info ["version" ] else "v0"
207
+
208
+ mp .log .info (f"got project info: local version { local_version } / server version { server_version } " )
209
+
210
+ username = mc .username ()
211
+ # permissions field contains information about update, delete and upload privileges of the user
212
+ # on a specific project. This is more accurate information than "writernames" field, as it takes
213
+ # into account namespace privileges. So we have to check only "permissions", namely "upload" once
214
+ if not mc .has_writing_permissions (project_path ):
215
+ mp .log .error (f"--- push { project_path } - username { username } does not have write access" )
216
+ raise ClientError (f"You do not seem to have write access to the project (username '{ username } ')" )
217
+
218
+ if local_version != server_version :
219
+ mp .log .error (f"--- push { project_path } - not up to date (local { local_version } vs server { server_version } )" )
220
+ raise ClientError (
221
+ "There is a new version of the project on the server. Please update your local copy."
222
+ + f"\n \n Local version: { local_version } \n Server version: { server_version } "
223
+ )
214
224
215
225
changes = change_batch or mp .get_push_changes ()
216
226
mp .log .debug ("push change:\n " + pprint .pformat (changes ))
@@ -288,16 +298,16 @@ def push_project_async(mc, directory, change_batch=None) -> Optional[UploadJob]:
288
298
289
299
total_size += file_size
290
300
291
- job .total_size = total_size
292
- job .upload_queue_items = upload_queue_items
301
+ job .total_size = total_size
302
+ job .upload_queue_items = upload_queue_items
293
303
294
- mp .log .info (f"will upload { len (upload_queue_items )} items with total size { total_size } " )
304
+ mp .log .info (f"will upload { len (upload_queue_items )} items with total size { total_size } " )
295
305
296
- # start uploads in background
297
- job .executor = concurrent .futures .ThreadPoolExecutor (max_workers = 4 )
298
- for item in upload_queue_items :
299
- future = job .executor .submit (_do_upload , item , job )
300
- job .futures .append (future )
306
+ # start uploads in background
307
+ job .executor = concurrent .futures .ThreadPoolExecutor (max_workers = 4 )
308
+ for item in upload_queue_items :
309
+ future = job .executor .submit (_do_upload , item , job )
310
+ job .futures .append (future )
301
311
302
312
return job
303
313
@@ -435,7 +445,9 @@ def total_upload_size(directory) -> int:
435
445
mp = MerginProject (directory )
436
446
changes = mp .get_push_changes ()
437
447
files = changes .get ("added" , []) + changes .get ("updated" , [])
438
- return sum (
448
+ size = sum (
439
449
f .get ("diff" , {}).get ("size" , f .get ("size" , 0 ))
440
450
for f in files
441
- )
451
+ )
452
+ mp .log .info (f"Upload size of all files is { size } " )
453
+ return size
0 commit comments