@@ -509,180 +509,312 @@ fn assign_sources_targets(
509509 }
510510}
511511
512- /// Extracts (real or derived from merge summary) and assigns basic properties.
513- fn extract_branches (
512+
513+ /// Extracts and processes actual Git branches (local and remote) from the repository.
514+ ///
515+ /// This function iterates through the branches found in the Git repository,
516+ /// filters them based on the `include_remote` setting, and constructs `BranchInfo`
517+ /// objects for each valid branch. It assigns properties like name, type (local/remote),
518+ /// visual order, and colors based on the provided settings.
519+ ///
520+ /// Arguments:
521+ /// - `repository`: A reference to the Git `Repository` object.
522+ /// - `indices`: A HashMap mapping commit OIDs to their corresponding indices in the `commits` list.
523+ /// - `settings`: A reference to the application `Settings` containing branch configuration.
524+ /// - `counter`: A mutable reference to a counter, incremented for each processed branch to aid in color assignment.
525+ ///
526+ /// Returns:
527+ /// A `Result` containing a `Vec<BranchInfo>` on success, or a `String` error message on failure.
528+ fn extract_actual_branches (
514529 repository : & Repository ,
515- commits : & [ CommitInfo ] ,
516530 indices : & HashMap < Oid , usize > ,
517531 settings : & Settings ,
532+ counter : & mut usize ,
518533) -> Result < Vec < BranchInfo > , String > {
534+ // Determine if remote branches should be included based on settings.
519535 let filter = if settings. include_remote {
520536 None
521537 } else {
522538 Some ( BranchType :: Local )
523539 } ;
540+
541+ // Retrieve branches from the repository, handling potential errors.
524542 let actual_branches = repository
525543 . branches ( filter)
526544 . map_err ( |err| err. message ( ) . to_string ( ) ) ?
527545 . collect :: < Result < Vec < _ > , Error > > ( )
528546 . map_err ( |err| err. message ( ) . to_string ( ) ) ?;
529547
530- let mut counter = 0 ;
531-
532- let mut valid_branches = actual_branches
548+ // Process each actual branch to create `BranchInfo` objects.
549+ let valid_branches = actual_branches
533550 . iter ( )
534551 . filter_map ( |( br, tp) | {
535552 br. get ( ) . name ( ) . and_then ( |n| {
536553 br. get ( ) . target ( ) . map ( |t| {
537- counter += 1 ;
554+ * counter += 1 ; // Increment counter for unique branch identification/coloring.
555+
556+ // Determine the starting index for slicing the branch name string.
538557 let start_index = match tp {
539- BranchType :: Local => 11 ,
540- BranchType :: Remote => 13 ,
558+ BranchType :: Local => 11 , // "refs/heads/"
559+ BranchType :: Remote => 13 , // "refs/remotes/"
541560 } ;
542561 let name = & n[ start_index..] ;
543562 let end_index = indices. get ( & t) . cloned ( ) ;
544563
564+ // Convert branch color to a terminal-compatible format.
545565 let term_color = match to_terminal_color (
546566 & branch_color (
547567 name,
548568 & settings. branches . terminal_colors [ ..] ,
549569 & settings. branches . terminal_colors_unknown ,
550- counter,
570+ * counter,
551571 ) [ ..] ,
552572 ) {
553573 Ok ( col) => col,
554- Err ( err) => return Err ( err) ,
574+ Err ( err) => return Err ( err) , // Propagate color conversion errors.
555575 } ;
556576
577+ // Create and return the BranchInfo object.
557578 Ok ( BranchInfo :: new (
558579 t,
559- None ,
580+ None , // No merge OID for actual branches.
560581 name. to_string ( ) ,
561582 branch_order ( name, & settings. branches . persistence ) as u8 ,
562- & BranchType :: Remote == tp,
563- false ,
564- false ,
583+ & BranchType :: Remote == tp, // Check if it's a remote branch.
584+ false , // Not a derived merge branch.
585+ false , // Not a tag.
565586 BranchVis :: new (
566587 branch_order ( name, & settings. branches . order ) ,
567588 term_color,
568589 branch_color (
569590 name,
570591 & settings. branches . svg_colors ,
571592 & settings. branches . svg_colors_unknown ,
572- counter,
593+ * counter,
573594 ) ,
574595 ) ,
575596 end_index,
576597 ) )
577598 } )
578599 } )
579600 } )
580- . collect :: < Result < Vec < _ > , String > > ( ) ?;
601+ . collect :: < Result < Vec < _ > , String > > ( ) ?; // Collect results, propagating any errors.
581602
603+ Ok ( valid_branches)
604+ }
605+
606+ /// Iterates through commits, identifies merge commits, and derives branch information
607+ /// from their summaries.
608+ ///
609+ /// This function processes each commit in the provided list. If a commit is identified
610+ /// as a merge commit and has a summary, it attempts to parse a branch name from the summary.
611+ /// A `BranchInfo` object is then created for this derived branch, representing the merge
612+ /// point and its properties.
613+ ///
614+ /// Arguments:
615+ /// - `repository`: A reference to the Git `Repository` object.
616+ /// - `commits`: A slice of `CommitInfo` objects, representing the commits to process.
617+ /// - `settings`: A reference to the application `Settings` containing branch and merge pattern configuration.
618+ /// - `counter`: A mutable reference to a counter, incremented for each processed merge branch.
619+ ///
620+ /// Returns:
621+ /// A `Result` containing a `Vec<BranchInfo>` on success, or a `String` error message on failure.
622+ fn extract_merge_branches (
623+ repository : & Repository ,
624+ commits : & [ CommitInfo ] ,
625+ settings : & Settings ,
626+ counter : & mut usize ,
627+ ) -> Result < Vec < BranchInfo > , String > {
628+ let mut merge_branches = Vec :: new ( ) ;
629+
630+ log:: debug!( "iterate commits for merge branches.." ) ;
631+ >>>>>>> Conflict 2 of 5 ends
582632 for ( idx, info) in commits. iter ( ) . enumerate ( ) {
583- let commit = repository
584- . find_commit ( info. oid )
585- . map_err ( |err| err. message ( ) . to_string ( ) ) ?;
633+ // Only process if the commit is a merge.
586634 if info. is_merge {
635+ let commit = repository
636+ . find_commit ( info. oid )
637+ . map_err ( |err| err. message ( ) . to_string ( ) ) ?;
638+
639+ // Attempt to get the commit summary.
587640 if let Some ( summary) = commit. summary ( ) {
588- counter += 1 ;
641+ * counter += 1 ; // Increment counter for unique branch identification/coloring.
589642
590643 let parent_oid = commit
591644 . parent_id ( 1 )
592645 . map_err ( |err| err. message ( ) . to_string ( ) ) ?;
593646
647+ // Parse the branch name from the merge summary using configured patterns.
594648 let branch_name = parse_merge_summary ( summary, & settings. merge_patterns )
595649 . unwrap_or_else ( || "unknown" . to_string ( ) ) ;
596650
651+ // Determine persistence and order for the derived branch.
597652 let persistence = branch_order ( & branch_name, & settings. branches . persistence ) as u8 ;
598-
599653 let pos = branch_order ( & branch_name, & settings. branches . order ) ;
600654
655+ // Get terminal and SVG colors for the branch.
601656 let term_col = to_terminal_color (
602657 & branch_color (
603658 & branch_name,
604659 & settings. branches . terminal_colors [ ..] ,
605660 & settings. branches . terminal_colors_unknown ,
606- counter,
661+ * counter,
607662 ) [ ..] ,
608663 ) ?;
609664 let svg_col = branch_color (
610665 & branch_name,
611666 & settings. branches . svg_colors ,
612667 & settings. branches . svg_colors_unknown ,
613- counter,
668+ * counter,
614669 ) ;
615670
671+ // Create and add the BranchInfo for the derived merge branch.
616672 let branch_info = BranchInfo :: new (
617- parent_oid,
618- Some ( info. oid ) ,
673+ parent_oid, // Target is the parent of the merge.
674+ Some ( info. oid ) , // The merge commit itself.
619675 branch_name,
620676 persistence,
621- false ,
622- true ,
623- false ,
677+ false , // Not a remote branch.
678+ true , // This is a derived merge branch.
679+ false , // Not a tag.
624680 BranchVis :: new ( pos, term_col, svg_col) ,
625- Some ( idx + 1 ) ,
681+ Some ( idx + 1 ) , // End index typically points to the commit after the merge.
626682 ) ;
627- valid_branches . push ( branch_info) ;
683+ merge_branches . push ( branch_info) ;
628684 }
629685 }
630686 }
687+ Ok ( merge_branches)
688+ }
631689
632- valid_branches. sort_by_cached_key ( |branch| ( branch. persistence , !branch. is_merged ) ) ;
633-
634- let mut tags = Vec :: new ( ) ;
690+ /// Extracts Git tags and treats them as branches, assigning appropriate properties.
691+ ///
692+ /// This function iterates through all tags in the repository, resolves their target
693+ /// commit OID, and if the target commit is found within the `commits` list,
694+ /// a `BranchInfo` object is created for the tag. Tags are assigned a higher
695+ /// persistence value to ensure they are displayed prominently.
696+ ///
697+ /// Arguments:
698+ /// - `repository`: A reference to the Git `Repository` object.
699+ /// - `indices`: A HashMap mapping commit OIDs to their corresponding indices in the `commits` list.
700+ /// - `settings`: A reference to the application `Settings` containing branch configuration.
701+ /// - `counter`: A mutable reference to a counter, incremented for each processed tag.
702+ ///
703+ /// Returns:
704+ /// A `Result` containing a `Vec<BranchInfo>` on success, or a `String` error message on failure.
705+ fn extract_tags_as_branches (
706+ repository : & Repository ,
707+ indices : & HashMap < Oid , usize > ,
708+ settings : & Settings ,
709+ counter : & mut usize ,
710+ ) -> Result < Vec < BranchInfo > , String > {
711+ let mut tags_info = Vec :: new ( ) ;
712+ let mut tags_raw = Vec :: new ( ) ;
635713
714+ // Iterate over all tags in the repository.
636715 repository
637716 . tag_foreach ( |oid, name| {
638- tags . push ( ( oid, name. to_vec ( ) ) ) ;
639- true
717+ tags_raw . push ( ( oid, name. to_vec ( ) ) ) ;
718+ true // Continue iteration.
640719 } )
641720 . map_err ( |err| err. message ( ) . to_string ( ) ) ?;
642721
643- for ( oid, name) in tags {
644- let name = std:: str:: from_utf8 ( & name[ 5 ..] ) . map_err ( |err| err. to_string ( ) ) ?;
722+ for ( oid, name_bytes) in tags_raw {
723+ // Convert tag name bytes to a UTF-8 string. Tags typically start with "refs/tags/".
724+ let name = std:: str:: from_utf8 ( & name_bytes[ 5 ..] ) . map_err ( |err| err. to_string ( ) ) ?;
645725
726+ // Resolve the target OID of the tag. It could be a tag object or directly a commit.
646727 let target = repository
647728 . find_tag ( oid)
648729 . map ( |tag| tag. target_id ( ) )
649- . or_else ( |_| repository. find_commit ( oid) . map ( |_| oid) ) ;
730+ . or_else ( |_| repository. find_commit ( oid) . map ( |_| oid) ) ; // If not a tag object, try as a direct commit.
650731
651732 if let Ok ( target_oid) = target {
733+ // If the target commit is within our processed commits, create a BranchInfo.
652734 if let Some ( target_index) = indices. get ( & target_oid) {
653- counter += 1 ;
735+ * counter += 1 ; // Increment counter for unique tag identification/coloring.
736+
737+ // Get terminal and SVG colors for the tag.
654738 let term_col = to_terminal_color (
655739 & branch_color (
656740 name,
657741 & settings. branches . terminal_colors [ ..] ,
658742 & settings. branches . terminal_colors_unknown ,
659- counter,
743+ * counter,
660744 ) [ ..] ,
661745 ) ?;
662746 let pos = branch_order ( name, & settings. branches . order ) ;
663747 let svg_col = branch_color (
664748 name,
665749 & settings. branches . svg_colors ,
666750 & settings. branches . svg_colors_unknown ,
667- counter,
751+ * counter,
668752 ) ;
753+
754+ // Create the BranchInfo object for the tag.
669755 let tag_info = BranchInfo :: new (
670756 target_oid,
671- None ,
757+ None , // No merge OID for tags.
672758 name. to_string ( ) ,
673- settings. branches . persistence . len ( ) as u8 + 1 ,
674- false ,
675- false ,
676- true ,
759+ settings. branches . persistence . len ( ) as u8 + 1 , // Tags usually have highest persistence.
760+ false , // Not a remote branch.
761+ false , // Not a derived merge branch.
762+ true , // This is a tag.
677763 BranchVis :: new ( pos, term_col, svg_col) ,
678764 Some ( * target_index) ,
679765 ) ;
680- valid_branches . push ( tag_info) ;
766+ tags_info . push ( tag_info) ;
681767 }
682768 }
683769 }
770+ Ok ( tags_info)
771+ }
684772
685- Ok ( valid_branches)
773+
774+ /// Extracts (real or derived from merge summary) and assigns basic properties to branches and tags.
775+ ///
776+ /// This function orchestrates the extraction of branch information from various sources:
777+ /// 1. Actual Git branches (local and remote).
778+ /// 2. Branches derived from merge commit summaries.
779+ /// 3. Git tags, treated as branches for visualization purposes.
780+ ///
781+ /// It combines the results from these extraction steps, sorts them based on
782+ /// persistence and merge status, and returns a comprehensive list of `BranchInfo` objects.
783+ ///
784+ /// Arguments:
785+ /// - `repository`: A reference to the Git `Repository` object.
786+ /// - `commits`: A slice of `CommitInfo` objects, representing all relevant commits.
787+ /// - `indices`: A HashMap mapping commit OIDs to their corresponding indices in the `commits` list.
788+ /// - `settings`: A reference to the application `Settings` containing all necessary configuration.
789+ ///
790+ /// Returns:
791+ /// A `Result` containing a `Vec<BranchInfo>` on success, or a `String` error message on failure.
792+ fn extract_branches (
793+ repository : & Repository ,
794+ commits : & [ CommitInfo ] ,
795+ indices : & HashMap < Oid , usize > ,
796+ settings : & Settings ,
797+ ) -> Result < Vec < BranchInfo > , String > {
798+ let mut counter = 0 ; // Counter for unique branch/tag identification, especially for coloring.
799+ let mut all_branches: Vec < BranchInfo > = Vec :: new ( ) ;
800+
801+ // 1. Extract actual local and remote branches.
802+ let actual_branches = extract_actual_branches ( repository, indices, settings, & mut counter) ?;
803+ all_branches. extend ( actual_branches) ;
804+
805+ // 2. Extract branches derived from merge commit summaries.
806+ let merge_branches = extract_merge_branches ( repository, commits, settings, & mut counter) ?;
807+ all_branches. extend ( merge_branches) ;
808+
809+ // 3. Extract tags and treat them as branches for visualization.
810+ let tags_as_branches = extract_tags_as_branches ( repository, indices, settings, & mut counter) ?;
811+ all_branches. extend ( tags_as_branches) ;
812+
813+ // Sort all collected branches and tags.
814+ // Sorting criteria: first by persistence, then by whether they are merged (unmerged first).
815+ all_branches. sort_by_cached_key ( |branch| ( branch. persistence , !branch. is_merged ) ) ;
816+
817+ Ok ( all_branches)
686818}
687819
688820/// Traces back branches by following 1st commit parent,
0 commit comments