@@ -774,24 +774,91 @@ def __iter__(self):
774774 curr = curr [1 ]
775775
776776 def execute (self ):
777+ # First, collect all operations
778+ operations = []
777779 root = self .__root
778780 curr = root [1 ]
781+
782+ # First pass: collect operations and handle replace optimizations
779783 while curr is not root :
780784 if curr [1 ] is not root :
781785 op_first , op_second = curr [2 ], curr [1 ][2 ]
782786 if op_first .location == op_second .location and \
783787 type (op_first ) == RemoveOperation and \
784788 type (op_second ) == AddOperation :
785- yield ReplaceOperation ({
789+ operations . append ( ReplaceOperation ({
786790 'op' : 'replace' ,
787791 'path' : op_second .location ,
788792 'value' : op_second .operation ['value' ],
789- }, pointer_cls = self .pointer_cls ).operation
793+ }, pointer_cls = self .pointer_cls ).operation )
790794 curr = curr [1 ][1 ]
791795 continue
792-
793- yield curr [2 ].operation
796+
797+ operations . append ( curr [2 ].operation )
794798 curr = curr [1 ]
799+
800+ # Second pass: identify and sort move operations
801+ move_indices = []
802+ move_ops = []
803+
804+ for i , op in enumerate (operations ):
805+ if op ['op' ] == 'move' :
806+ move_indices .append (i )
807+ move_ops .append (op )
808+
809+ # Sort move operations based on dependencies
810+ if move_ops :
811+ # Create dependency graph: if op1's target is op2's source, op2 depends on op1
812+ dependencies = {}
813+ for i , op1 in enumerate (move_ops ):
814+ dependencies [i ] = []
815+ src1 = op1 ['from' ]
816+ tgt1 = op1 ['path' ]
817+
818+ for j , op2 in enumerate (move_ops ):
819+ if i == j :
820+ continue # Skip self-comparison
821+
822+ src2 = op2 ['from' ]
823+
824+ # If op2's source is the same as op1's target, op2 should come after op1
825+ if src2 == tgt1 or src2 .startswith (tgt1 + '/' ):
826+ dependencies [i ].append (j )
827+
828+ # Topological sort to determine execution order
829+ # We're using a simple approach: if op1 depends on op2, op2 should be executed first
830+ sorted_indices = []
831+ visited = set ()
832+ temp_visited = set ()
833+
834+ def visit (i ):
835+ if i in temp_visited :
836+ # Cyclic dependency - maintain original order
837+ return
838+ if i in visited :
839+ return
840+
841+ temp_visited .add (i )
842+
843+ for j in dependencies .get (i , []):
844+ visit (j )
845+
846+ temp_visited .remove (i )
847+ visited .add (i )
848+ sorted_indices .append (i )
849+
850+ for i in range (len (move_ops )):
851+ if i not in visited :
852+ visit (i )
853+
854+ # Replace original move operations with sorted ones
855+ sorted_move_ops = [move_ops [i ] for i in sorted_indices ]
856+ for idx , op in zip (move_indices , sorted_move_ops ):
857+ operations [idx ] = op
858+
859+ # Yield operations
860+ for op in operations :
861+ yield op
795862
796863 def _item_added (self , path , key , item ):
797864 index = self .take_index (item , _ST_REMOVE )
0 commit comments