collaboration.merge module

binaryninja.collaboration.merge.ConflictFormatter([...])

Helper class that turns json conflicts into pretty text for the ui to render

binaryninja.collaboration.merge.ConflictHandler([...])

Helper class that resolves conflicts

binaryninja.collaboration.merge.ConflictSplitter([...])

Helper class that takes one merge conflict and splits it into multiple conflicts Eg takes conflicts for View/symbols and splits to one conflict per symbol

binaryninja.collaboration.merge.CoreConflictFormatter([...])

FFI wrapper for conflict formatters

binaryninja.collaboration.merge.CoreConflictSplitter([...])

FFI wrapper for core-constructed splitters

binaryninja.collaboration.merge.FormattedConflict([...])

Class taking a merge conflict and producing a formatted text output.

binaryninja.collaboration.merge.FormatterList()

Mutable list of formatters for FFI purposes

binaryninja.collaboration.merge.MergeConflict(handle)

Structure representing an individual merge conflict

binaryninja.collaboration.merge.SplitterList()

Mutable list of splitters for FFI purposes

class ConflictFormatter(handle=None)[source]

Bases: object

Helper class that turns json conflicts into pretty text for the ui to render

abstract can_format(key: str, conflict: MergeConflict) bool[source]

Test if the formatter can format a specific conflict

Parameters:
  • key (str) – Unique key for the conflict

  • conflict (MergeConflict) – Conflict structure

Returns:

True if the formatter should try to format this conflict

Return type:

bool

abstract format(key: str, conflict: MergeConflict) Optional[FormattedConflict][source]

Format a conflict into a human-readable string

Parameters:
  • key (str) – Unique key for the conflict

  • conflict (MergeConflict) – Conflict structure

Returns:

Formatted conflict structure, if it could be formatted. None otherwise.

Return type:

Optional[FormattedConflict]

get_name() str[source]

Get a friendly name for the formatter

Returns:

Name of the formatter

Return type:

str

property name

Get a friendly name for the formatter

Returns:

Name of the formatter

class ConflictHandler(handle=None)[source]

Bases: object

Helper class that resolves conflicts

abstract handle(conflicts: Dict[str, MergeConflict]) bool[source]

Handle any merge conflicts by calling their success() function with a merged value

Parameters:

conflicts (Dict[str, MergeConflict]) – Map of conflict id to conflict structure

Returns:

True if all conflicts were successfully merged

Return type:

bool

class ConflictSplitter(handle=None)[source]

Bases: object

Helper class that takes one merge conflict and splits it into multiple conflicts Eg takes conflicts for View/symbols and splits to one conflict per symbol

abstract can_split(key: str, conflict: MergeConflict) bool[source]

Test if the splitter applies to a given conflict (by key).

Parameters:
  • key (str) – Key of the conflicting field

  • conflict (MergeConflict) – Conflict data

Returns:

True if this splitter should be used on the conflict

Return type:

bool

get_name() str[source]

Get a friendly name for the splitter

Returns:

Name of the splitter

Return type:

str

abstract split(key: str, conflict: MergeConflict, result: KeyValueStore) Optional[Dict[str, MergeConflict]][source]

Split a field conflict into any number of alternate conflicts. Note: Returned conflicts will also be checked for splitting, beware infinite loops! If this function raises, it will be treated as returning None

Parameters:
  • key (str) – Original conflicting field’s key

  • conflict (MergeConflict) – Original conflict data

  • result (KeyValueStore) – Kvs structure containing the result of all splits. You should use the original conflict’s success() function in most cases unless you specifically want to write a new key to this.

Returns:

A collection of conflicts into which the original conflict was split, or None if this splitter cannot handle the conflict

Return type:

Optional[Dict[str, MergeConflict]]

property name

Get a friendly name for the splitter

Returns:

Name of the splitter

class CoreConflictFormatter(handle=None)[source]

Bases: ConflictFormatter

FFI wrapper for conflict formatters

can_format(key: str, conflict: MergeConflict) bool[source]

Test if the formatter can format a specific conflict

Parameters:
  • key (str) – Unique key for the conflict

  • conflict (MergeConflict) – Conflict structure

Returns:

True if the formatter should try to format this conflict

Return type:

bool

format(key: str, conflict: MergeConflict) Optional[FormattedConflict][source]

Format a conflict into a human-readable string

Parameters:
  • key (str) – Unique key for the conflict

  • conflict (MergeConflict) – Conflict structure

Returns:

Formatted conflict structure, if it could be formatted. None otherwise.

Return type:

Optional[FormattedConflict]

get_name() str[source]

Get a friendly name for the formatter

Returns:

Name of the formatter

Return type:

str

class CoreConflictSplitter(handle=None)[source]

Bases: ConflictSplitter

FFI wrapper for core-constructed splitters

can_split(key: str, conflict: MergeConflict) bool[source]

Test if the splitter applies to a given conflict (by key).

Parameters:
  • key (str) – Key of the conflicting field

  • conflict (MergeConflict) – Conflict data

Returns:

True if this splitter should be used on the conflict

Return type:

bool

get_name() str[source]

Get a friendly name for the splitter

Returns:

Name of the splitter

Return type:

str

split(key: str, conflict: MergeConflict, result: KeyValueStore) Optional[Dict[str, MergeConflict]][source]

Split a field conflict into any number of alternate conflicts. Note: Returned conflicts will also be checked for splitting, beware infinite loops! If this function raises, it will be treated as returning None

Parameters:
  • key (str) – Original conflicting field’s key

  • conflict (MergeConflict) – Original conflict data

  • result (KeyValueStore) – Kvs structure containing the result of all splits. You should use the original conflict’s success() function in most cases unless you specifically want to write a new key to this.

Returns:

A collection of conflicts into which the original conflict was split, or None if this splitter cannot handle the conflict

Return type:

Optional[Dict[str, MergeConflict]]

class FormattedConflict(conflict: Optional[MergeConflict] = None, type: Optional[FormattedConflictFormatType] = None, name: Optional[str] = None, base_text: Optional[str] = None, first_text: Optional[str] = None, second_text: Optional[str] = None, base: Optional[Dict[str, object]] = None, first: Optional[Dict[str, object]] = None, second: Optional[Dict[str, object]] = None, handle=None)[source]

Bases: object

Class taking a merge conflict and producing a formatted text output.

Parameters:
property base: Optional[Dict[str, object]]

Json of base first of conflict

Returns:

Formatted Json value, if type = Code, else None

property base_text: Optional[str]

Text of base version of conflict

Returns:

Formatted text, if type = Text, else None

property conflict: MergeConflict

Unformatted merge conflict structure

Returns:

Merge Conflict structure

property first: Optional[Dict[str, object]]

Json of first first of conflict

Returns:

Formatted Json value, if type = Code, else None

property first_text: Optional[str]

Text of first version of conflict

Returns:

Formatted text, if type = Text, else None

property name: str

Formatted name of conflict

Returns:

Name string

property second: Optional[Dict[str, object]]

Json of second first of conflict

Returns:

Formatted Json value, if type = Code, else None

property second_text: Optional[str]

Text of second version of conflict

Returns:

Formatted text, if type = Text, else None

property type: FormattedConflictFormatType

Type of formatted content (Text/Code)

Returns:

Type

class FormatterList[source]

Bases: MutableSequence

Mutable list of formatters for FFI purposes

insert(index: int, value: ConflictFormatter) None[source]

S.insert(index, value) – insert value before index

Parameters:
Return type:

None

class MergeConflict(handle)[source]

Bases: object

Structure representing an individual merge conflict

get_path_item(path_key: str) Optional[object][source]

Get item in the merge conflict’s path for a given key.

Parameters:

path_key (str) – Key for path item

Returns:

Path item, or an None if not found

Return type:

Optional[object]

make_child(new_data_type, new_type: str, new_key: str, new_path_key: str, new_path_value: object, new_base: Optional[Dict[str, object]], new_first: Optional[Dict[str, object]], new_second: Optional[Dict[str, object]], new_success: Callable[[Optional[Dict[str, object]]], bool])[source]

Convenience function for making a new merge conflict using the snapshots/storage from this one

Parameters:
  • new_data_type – Desired dataType of new conflict

  • new_type (str) – Desired type of new conflict

  • new_key (str) – Desired key of new conflict

  • new_path_key (str) – Key to add to path for new conflict

  • new_path_value (object) – Value for key added to path

  • new_base (Optional[Dict[str, object]]) – Desired base of new conflict

  • new_first (Optional[Dict[str, object]]) – Desired first of new conflict

  • new_second (Optional[Dict[str, object]]) – Desired second of new conflict

  • new_success (Callable[[Optional[Dict[str, object]]], bool]) – Success function for new conflict

Returns:

Created child object

success(value: Optional[Dict[str, object]]) bool[source]

Call this when you’ve resolved the conflict to save the result

Parameters:

value (Optional[Dict[str, object]]) – Resolved value

Returns:

True if successful

Return type:

bool

property base: Optional[Dict[str, object]]

Json object for conflicting data in the base snapshot

Returns:

Python dictionary from parsed json

property base_file: Optional[FileMetadata]

FileMetadata with contents of file for base snapshot This function is slow! Only use it if you really need it.

Returns:

FileMetadata object

property base_snapshot: Optional[Snapshot]

Snapshot which is the parent of the two being merged

Returns:

Snapshot object

property data_type: MergeConflictDataType

Type of data in the conflict, Text/Json/Binary

Returns:

Conflict data type

property database: Database

Database backing all snapshots in the merge conflict

Returns:

Database object

property first: Optional[Dict[str, object]]

Json object for conflicting data in the first snapshot

Returns:

Python dictionary from parsed json

property first_file: Optional[FileMetadata]

FileMetadata with contents of file for first snapshot This function is slow! Only use it if you really need it.

Returns:

FileMetadata object

property first_snapshot: Optional[Snapshot]

First snapshot being merged

Returns:

Snapshot object

property key: str

Lookup key for the merge conflict, ideally a tree path that contains the name of the conflict and all the recursive children leading up to this conflict.

Returns:

Key name

property second: Optional[Dict[str, object]]

Json object for conflicting data in the second snapshot

Returns:

Python dictionary from parsed json

property second_file: Optional[FileMetadata]

FileMetadata with contents of file for second snapshot This function is slow! Only use it if you really need it.

Returns:

FileMetadata object

property second_snapshot: Optional[Snapshot]

Second snapshot being merged

Returns:

Snapshot object

property type: str

String representing the type name of the data, not the same as data_type. This is like “typeName” or “tag” depending on what object the conflict represents.

Returns:

Type name

class SplitterList[source]

Bases: MutableSequence

Mutable list of splitters for FFI purposes

insert(index: int, value: ConflictSplitter) None[source]

S.insert(index, value) – insert value before index

Parameters:
Return type:

None

diff_kvs(base: KeyValueStore, target: KeyValueStore) Dict[str, List[str]][source]

Calculate the difference between two KVS structures

Parameters:
Returns:

Map: {“added”: [added fields], “modified”: [modified fields], “removed”: [removed fields]}

Return type:

Dict[str, List[str]]

least_common_ancestor(first: Snapshot, second: Snapshot) Optional[Snapshot][source]

Get the least common ancestor snapshot between two snapshots. The two snapshots must be in the same database.

Parameters:
  • first (Snapshot) – First snapshot for ancestor searching

  • second (Snapshot) – First snapshot for ancestor searching

Returns:

Ancestor snapshot, or None if the snapshots are on disjoint trees

Return type:

Optional[Snapshot]

merge_kvs(database: Database, base: Snapshot, first: Snapshot, second: Snapshot, conflict_handler: ConflictHandler, progress: Callable[[int, int], bool]) Optional[KeyValueStore][source]

Merge the underlying KVS data structure in two snapshots.

Parameters:
  • database (Database) – Owning database

  • base (Snapshot) – ancestor snapshot’s data

  • first (Snapshot) – First snapshot’s data

  • second (Snapshot) – Second snapshot’s data

  • conflict_handler (ConflictHandler) – Function to call when merge conflicts are encountered

  • progress (Callable[[int, int], bool]) – Function to call for progress updates and cancelling

Returns:

Merged KVS structure, or None if there was an error

Return type:

Optional[KeyValueStore]

merge_snapshots(first: Snapshot, second: Snapshot, conflict_handler: ConflictHandler, progress: Callable[[int, int], bool]) Optional[Snapshot][source]

Merge a pair of snapshots and create a new snapshot with the result.

Parameters:
  • first (Snapshot) – First snapshot to merge

  • second (Snapshot) – Second snapshot to merge

  • conflict_handler (ConflictHandler) – Function to call when merge conflicts are encountered

  • progress (Callable[[int, int], bool]) – Function to call for progress updates and cancelling

Returns:

Result snapshot, or None if there was an error

Return type:

Optional[Snapshot]