p4cmd 2.6.0__tar.gz → 2.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {p4cmd-2.6.0 → p4cmd-2.8.0}/PKG-INFO +1 -1
  2. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/__init__.py +1 -1
  3. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/p4cmd.py +120 -2
  4. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd.egg-info/PKG-INFO +1 -1
  5. {p4cmd-2.6.0 → p4cmd-2.8.0}/LICENSE +0 -0
  6. {p4cmd-2.6.0 → p4cmd-2.8.0}/README.md +0 -0
  7. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/p4errors.py +0 -0
  8. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/p4file.py +0 -0
  9. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/resources/__init__.py +0 -0
  10. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/resources/perforce_DEPOT_ONLY.png +0 -0
  11. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/resources/perforce_MOVED.png +0 -0
  12. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/resources/perforce_NEED_SYNC.png +0 -0
  13. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/resources/perforce_OPEN_FOR_ADD.png +0 -0
  14. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/resources/perforce_OPEN_FOR_DELETE.png +0 -0
  15. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/resources/perforce_OPEN_FOR_EDIT.png +0 -0
  16. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/resources/perforce_UNKNOWN.png +0 -0
  17. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/resources/perforce_UNTRACKED.png +0 -0
  18. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/resources/perforce_UP_TO_DATE.png +0 -0
  19. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd/utils.py +0 -0
  20. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd.egg-info/SOURCES.txt +0 -0
  21. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd.egg-info/dependency_links.txt +0 -0
  22. {p4cmd-2.6.0 → p4cmd-2.8.0}/p4cmd.egg-info/top_level.txt +0 -0
  23. {p4cmd-2.6.0 → p4cmd-2.8.0}/setup.cfg +0 -0
  24. {p4cmd-2.6.0 → p4cmd-2.8.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: p4cmd
3
- Version: 2.6.0
3
+ Version: 2.8.0
4
4
  Summary: Simple P4 python module
5
5
  Home-page: https://github.com/nielsvaes/p4cmd
6
6
  Author: Niels Vaes
@@ -1,4 +1,4 @@
1
- VERSION = "2.6.0"
1
+ VERSION = "2.8.0"
2
2
 
3
3
  from .p4cmd import P4Client
4
4
  from .p4file import P4File
@@ -306,7 +306,73 @@ class P4Client(object):
306
306
  if len(changelists):
307
307
  return True
308
308
  return False
309
+
310
+ def update_changelist_description(self, changelist, new_description):
311
+ """
312
+ Updates the description of an existing changelist.
309
313
 
314
+ :param changelist: *string* or *int* changelist number
315
+ :param new_description: *string* new description for the changelist
316
+ :return: *bool* True if successful, False otherwise
317
+ """
318
+
319
+ # ... not super elegant, but it works
320
+ try:
321
+ changelist = self.__ensure_changelist(changelist)
322
+
323
+ # do some formatting so that we have the proper indentation
324
+ formatted_description = []
325
+ for line in new_description.split('\n'):
326
+ formatted_description.append(f"\t{line}")
327
+ formatted_description = '\n'.join(formatted_description)
328
+
329
+ output = subprocess.check_output(f'p4 change -o {changelist}', shell=True).decode()
330
+
331
+ # Split the output into sections based on field names
332
+ sections = []
333
+ current_section = []
334
+ current_field = None
335
+
336
+ # take the output and start parsing it
337
+ for line in output.split('\n'):
338
+ # check if it's a new field
339
+ if line.strip() and ':' in line and not line.startswith('\t'):
340
+ # if it is, save the previous section
341
+ if current_field:
342
+ sections.append((current_field, current_section))
343
+ # now start a new section
344
+ current_field = line.split(':', 1)[0].strip()
345
+ current_section = [line]
346
+ else:
347
+ # if it's not a new field, add to the current section
348
+ current_section.append(line)
349
+
350
+ # add the last section
351
+ if current_field:
352
+ sections.append((current_field, current_section))
353
+
354
+ # new remake the Description field with the update description
355
+ new_output = []
356
+ for field, section_lines in sections:
357
+ if field == "Description":
358
+ # replace the description section
359
+ new_output.append(section_lines[0]) # keep the "Description:" line because perforce needs this
360
+ new_output.append(formatted_description)
361
+ else:
362
+ # keep everything else as-is
363
+ new_output.extend(section_lines)
364
+
365
+ updated_output = '\n'.join(new_output)
366
+
367
+ # TODO: modify run_cmd to allow input so that commands like this can also run through it.
368
+ result = subprocess.check_output(f'p4 change -i', input=updated_output.encode(), shell=True).decode()
369
+
370
+ return True
371
+ except Exception as e:
372
+ if not self.silent:
373
+ logging.error(f"Failed to update changelist description: {e}")
374
+ return False
375
+
310
376
  @validate_not_empty
311
377
  def move_files_to_changelist(self, file_list, changelist="default"):
312
378
  """
@@ -563,16 +629,26 @@ class P4Client(object):
563
629
  info_dicts = self.run_cmd("delete", args=["-c", changelist], file_list=file_list)
564
630
  return info_dicts
565
631
 
566
- def delete_changelist(self, changelist="default", perfect_match_only=False, case_sensitive=False):
632
+ def delete_changelist(self, changelist, perfect_match_only=False, case_sensitive=False, delete_shelved_files=False, obliterate=False):
567
633
  """
568
- Deletes a changelist via changelist number or description
634
+ Deletes a changelist via changelist number or description. Will fail if any files are checked out or shelved files exist.
569
635
  :param changelist: *string* or *int* change list number
570
636
  :param perfect_match_only: bool* only delete if there's a perfect match of the changelist description
571
637
  :param case_sensitive: *bool*
638
+ :param delete_shelved_files: *bool* If True, will delete all shelved files and then delete the CL.
639
+ :param obliterate: *bool* If True, will revert all files, deleted shelved files and then delete the CL
572
640
  """
573
641
  info_dicts = []
574
642
  cl_num = self.get_pending_changelists(changelist, perfect_match_only, case_sensitive)
575
643
  for cl in cl_num:
644
+ # revert all files, then make sure shelved files are also deleted
645
+ if obliterate:
646
+ info_dicts.append(self.revert_changelist(changelist=cl))
647
+ delete_shelved_files = True
648
+
649
+ if delete_shelved_files:
650
+ info_dicts.append(self.delete_shelf(cl))
651
+
576
652
  info_dicts.append(self.run_cmd('change', args=['-d', cl]))
577
653
  # TODO: Break down info dicts and look for errors
578
654
  return info_dicts
@@ -707,6 +783,48 @@ class P4Client(object):
707
783
 
708
784
  return info_dicts
709
785
 
786
+ def delete_shelf(self, changelist):
787
+ """
788
+ Deletes all shelved files in a changelist without deleting the changelist itself.
789
+
790
+ :param changelist: *string* or *int* changelist number
791
+ :return: *list* of info dictionaries
792
+ """
793
+ try:
794
+ # Ensure the changelist exists and is a number
795
+ changelist = self.__ensure_changelist(changelist)
796
+
797
+ # Don't allow deleting shelves from the default changelist
798
+ if changelist == "default":
799
+ if not self.silent:
800
+ logging.error("Cannot delete shelved files from the default changelist")
801
+ return [{"code": "error", "data": "Cannot delete shelved files from the default changelist"}]
802
+
803
+ # Check if the changelist has shelved files
804
+ has_shelved_files = False
805
+ info_dicts = self.run_cmd("describe", args=["-S", str(changelist)])
806
+ for info_dict in info_dicts:
807
+ for key in info_dict.keys():
808
+ if b"depotFile" in key:
809
+ has_shelved_files = True
810
+ break
811
+ if has_shelved_files:
812
+ break
813
+
814
+ if not has_shelved_files:
815
+ if not self.silent:
816
+ logging.warning(f"No shelved files found in changelist {changelist}")
817
+ return [{"code": "info", "data": f"No shelved files found in changelist {changelist}"}]
818
+
819
+ # Delete all shelved files in the changelist
820
+ info_dicts = self.run_cmd("shelve", args=["-d", "-c", str(changelist)])
821
+ return info_dicts
822
+
823
+ except Exception as e:
824
+ if not self.silent:
825
+ logging.error(f"Failed to delete shelved files: {e}")
826
+ return [{"code": "error", "data": str(e)}]
827
+
710
828
  @validate_not_empty
711
829
  def add_or_edit_folders(self, folders, include_subfolders=True, changelist="default"):
712
830
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: p4cmd
3
- Version: 2.6.0
3
+ Version: 2.8.0
4
4
  Summary: Simple P4 python module
5
5
  Home-page: https://github.com/nielsvaes/p4cmd
6
6
  Author: Niels Vaes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes