Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Dump and Restore project to/from YAML #55

Closed
xslim opened this Issue · 11 comments

4 participants

@xslim

Sometimes when working on a project with big team we have problem when both person make change to project file and then one pulls changes and has problems merging project files.

To solve such thing, it can be interesting to actually commit a simple text file to SCM, like YAML, and then, restore the project from that file. That could make merging faster.

Google for it's own projects is using GYP

Maybe we can make some similar add-on?

@alloy
Owner

Sounds like a great idea to me!

@xslim

trying to compare possible formats:

File type Size Method
pbxproj 133K
raw.yml 780K xcodeproj.to_yaml
hash.yml 89K xcodeproj.to_hash.to_yaml
tree_hash.yml 192K xcodeproj.to_tree_hash.to_yaml
@fabiopelosin

Wow I didn't expect those sizes.

@fabiopelosin

What is raw.yml?

@xslim

check edited table with Method….

well, I figured out how to dump stuff… but what's the best way to restore it?

@xslim

I think for merge the best will be something like tree_hash, but it doesn't contain UUIDs, so that will always re-generate….

@fabiopelosin

I see, thanks.

The easiest way to restore it is to use xcodeproj.to_hash.to_yaml as it is just an alternative representation of the plist. The project can be initialed in the same way passing the contents of the YAML here. However this approach has the disadvantage of being less readable.

The other alternative is to use xcodeproj.to_tree_hash.to_yaml. However restoring the project is more complicated because for each object it is necessary to check which attributes represent relationships and create objects recursively according AbstractObject::from_tree_hash might be a suitable method. With this approach the yaml is much more readable but the UUIDS would change every time and there might be loss of information with duplicated references.

@xslim

What about having some middle-format between hash and tree_hash that includes UUIDs?
Also, I think that hash can be bade lighter if some assumptions are maid.
Example:

  • skip output the name if it's same as displayName
  • skip output the sourceTree if it's <group>
  • skip output isa if it is PBXFileReference

What do you think?

@fabiopelosin

A hybrid could be a good idea, however what I have in mind is not easy to implement. I'm thinking that a robust system but readable system would be a tree similar to tree_hash but replacing the objects with their UUID when they are referenced for the second time.

The issue of duplication is very common and is the following:

main_group:
- group:
  - the_file_reference:
    path: some_file.m

targets
  build_phases:
  - PBXSourcesBuildPhase
      files:
      - a build file which references
        file_ref: the_file_reference

This is the reason why they use UUIDs and the reason because the xcodeproj is unreadable to humans.


skip output the name if it's same as displayName

Display name is not an attribute is a ruby method and thus it doesn't need to be serialized. It was added to have a human readable description even for objects without name.

skip output the sourceTree if it's
skip output isa if it is PBXFileReference

I think that some experimentation would be needed but the implementation could get complicated.

@fabiopelosin fabiopelosin referenced this issue from a commit
@fabiopelosin fabiopelosin Merge branch 'master' of https://github.com/xslim/Xcodeproj into xsli…
…m-master

* 'master' of https://github.com/xslim/Xcodeproj:
  Added few yaml output formats for show command, to help developing #55
507469a
@fabiopelosin fabiopelosin changed the title from [Idea] Dump and Restore project to/from YAML to [Fun Idea] Dump and Restore project to/from YAML
@fabiopelosin fabiopelosin added fun idea and removed feature labels
@fabiopelosin fabiopelosin changed the title from [Fun Idea] Dump and Restore project to/from YAML to Dump and Restore project to/from YAML
@fabiopelosin

Closing due to lack of activity

@AliSoftware
Collaborator

(In case we reopen this someday)

Regarding avoiding duplication in the dumped YAML, why not using YAML's alias & anchors? This is exactly why they exist in the YAML standard.

main_group:
- group:
  - &file1
    sourceTree: <group>
    name: some_file.m
    path: foo/some_file.m
  - &file2
    sourceTree: <group>
    name: other_file.m
    path: bar/other_file.m

targets:
  build_phases:
  - PBXSourcesBuildPhase:
      files:
      - *file1
      - *file2

[1] pry(main)> require 'yaml'
[2] pry(main)> hash = YAML.load_file("the_file_above.yml")
=> {"main_group"=>
  [{"group"=>
     [{"sourceTree"=>"<group>", "name"=>"some_file.m", "path"=>"foo/some_file.m"},
      {"sourceTree"=>"<group>", "name"=>"other_file.m", "path"=>"bar/other_file.m"}]}],
 "targets"=>
  {"build_phases"=>
    [{"PBXSourcesBuildPhase"=>
       {"files"=>
         [{"sourceTree"=>"<group>", "name"=>"some_file.m", "path"=>"foo/some_file.m"},
          {"sourceTree"=>"<group>", "name"=>"other_file.m", "path"=>"bar/other_file.m"}]}}]}}

Actually it seems that Ruby's to_yaml create anchors and aliases automatically itself when a hash references the same object (same ruby's object id) multiple times — see how it creates &1/&2 and *1/*2 below)

[3] pry(main)> f1 = {"sourceTree"=>"<group>", "name"=>"some_file.m", "path"=>"foo/some_file.m"}
[4] pry(main)> f2 = {"sourceTree"=>"<group>", "name"=>"other_file.m", "path"=>"bar/other_file.m"}
[5] pry(main)> h = {"main_group"=>[{"group"=>[f1,f2]}], "targets"=>{"build_phases"=>[{"PBXSourcesBuildPhase"=>{"files"=>[f1,f2]}}]}}
[6] pry(main)> puts h.to_yaml
---
main_group:
- group:
  - &1
    sourceTree: "<group>"
    name: some_file.m
    path: foo/some_file.m
  - &2
    sourceTree: "<group>"
    name: other_file.m
    path: bar/other_file.m
targets:
  build_phases:
  - PBXSourcesBuildPhase:
      files:
      - *1
      - *2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.