3232from cycode .cli .utils .progress_bar import ScanProgressBarSection
3333from cycode .cli .utils .scan_batch import run_parallel_batched_scan
3434from cycode .cli .utils .scan_utils import set_issue_detected
35+ from cycode .cli .utils .shell_executor import shell
3536from cycode .cyclient import logger
3637from cycode .cyclient .config import set_logging_level
3738from cycode .cyclient .models import Detection , DetectionSchema , DetectionsPerFile , ZippedFileScanResult
@@ -666,6 +667,9 @@ def get_scan_parameters(context: click.Context, paths: Optional[Tuple[str]] = No
666667 return scan_parameters
667668
668669 remote_url = try_get_git_remote_url (paths [0 ])
670+ if not remote_url :
671+ remote_url = try_to_get_plastic_remote_url (paths [0 ])
672+
669673 if remote_url :
670674 # TODO(MarshalX): remove hardcode in context
671675 context .obj ['remote_url' ] = remote_url
@@ -684,6 +688,93 @@ def try_get_git_remote_url(path: str) -> Optional[str]:
684688 return None
685689
686690
691+ def _get_plastic_repository_name (path : str ) -> Optional [str ]:
692+ """Gets the name of the Plastic repository from the current working directory.
693+
694+ The command to execute is:
695+ cm status --header --machinereadable --fieldseparator=":::"
696+
697+ Example of status header in machine-readable format:
698+ STATUS:::0:::Project/RepoName:::OrgName@ServerInfo
699+ """
700+
701+ try :
702+ command = [
703+ 'cm' ,
704+ 'status' ,
705+ '--header' ,
706+ '--machinereadable' ,
707+ f'--fieldseparator={ consts .PLASTIC_VCS_DATA_SEPARATOR } ' ,
708+ ]
709+
710+ status = shell (command = command , timeout = consts .PLASTIC_VSC_CLI_TIMEOUT , working_directory = path )
711+ if not status :
712+ logger .debug ('Failed to get Plastic repository name (command failed)' )
713+ return None
714+
715+ status_parts = status .split (consts .PLASTIC_VCS_DATA_SEPARATOR )
716+ if len (status_parts ) < 2 :
717+ logger .debug ('Failed to parse Plastic repository name (command returned unexpected format)' )
718+ return None
719+
720+ return status_parts [2 ].strip ()
721+ except Exception as e :
722+ logger .debug ('Failed to get Plastic repository name' , exc_info = e )
723+ return None
724+
725+
726+ def _get_plastic_repository_list (working_dir : Optional [str ] = None ) -> Dict [str , str ]:
727+ """Gets the list of Plastic repositories and their GUIDs.
728+
729+ The command to execute is:
730+ cm repo list --format="{repname}:::{repguid}"
731+
732+ Example line with data:
733+ Project/RepoName:::tapo1zqt-wn99-4752-h61m-7d9k79d40r4v
734+
735+ Each line represents an individual repository.
736+ """
737+
738+ repo_name_to_guid = {}
739+
740+ try :
741+ command = ['cm' , 'repo' , 'ls' , f'--format={{repname}}{ consts .PLASTIC_VCS_DATA_SEPARATOR } {{repguid}}' ]
742+
743+ status = shell (command = command , timeout = consts .PLASTIC_VSC_CLI_TIMEOUT , working_directory = working_dir )
744+ if not status :
745+ logger .debug ('Failed to get Plastic repository list (command failed)' )
746+ return repo_name_to_guid
747+
748+ status_lines = status .splitlines ()
749+ for line in status_lines :
750+ data_parts = line .split (consts .PLASTIC_VCS_DATA_SEPARATOR )
751+ if len (data_parts ) < 2 :
752+ logger .debug ('Failed to parse Plastic repository list line (unexpected format), %s' , {'line' : line })
753+ continue
754+
755+ repo_name , repo_guid = data_parts
756+ repo_name_to_guid [repo_name .strip ()] = repo_guid .strip ()
757+
758+ return repo_name_to_guid
759+ except Exception as e :
760+ logger .debug ('Failed to get Plastic repository list' , exc_info = e )
761+ return repo_name_to_guid
762+
763+
764+ def try_to_get_plastic_remote_url (path : str ) -> Optional [str ]:
765+ repository_name = _get_plastic_repository_name (path )
766+ if not repository_name :
767+ return None
768+
769+ repository_map = _get_plastic_repository_list (path )
770+ if repository_name not in repository_map :
771+ logger .debug ('Failed to get Plastic repository GUID (repository not found in the list)' )
772+ return None
773+
774+ repository_guid = repository_map [repository_name ]
775+ return f'{ consts .PLASTIC_VCS_REMOTE_URI_PREFIX } { repository_guid } '
776+
777+
687778def exclude_irrelevant_detections (
688779 detections : List [Detection ], scan_type : str , command_scan_type : str , severity_threshold : str
689780) -> List [Detection ]:
0 commit comments