diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b1063e0b..db09f754 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,7 +76,7 @@ jobs: with: run: | set -e - make assets_manifest + make assets_rebuild assets_manifest git diff --quiet || ( echo "Assets recompilation required."; exit 255 ) - name: 'Build the firmware in docker' diff --git a/Makefile b/Makefile index d90c4e73..ca3caa22 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,6 @@ ifeq ($(FORCE), 1) endif @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) flash - .PHONY: updater updater: @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) RAM_EXEC=1 all @@ -97,14 +96,16 @@ updater_package_bin: firmware_all updater @$(PROJECT_ROOT)/scripts/dist.py copy -t $(TARGET) -p firmware updater -s $(DIST_SUFFIX) --bundlever "$(VERSION_STRING)" .PHONY: updater_package -updater_package: firmware_all updater - @$(PROJECT_ROOT)/scripts/dist.py copy -t $(TARGET) -p firmware updater -s $(DIST_SUFFIX) -a assets/resources --bundlever "$(VERSION_STRING)" +updater_package: firmware_all updater assets_manifest + @$(PROJECT_ROOT)/scripts/dist.py copy -t $(TARGET) -p firmware updater -s $(DIST_SUFFIX) -r $(PROJECT_ROOT)/assets/resources --bundlever "$(VERSION_STRING)" .PHONY: assets_manifest assets_manifest: - @$(MAKE) -C $(PROJECT_ROOT)/assets clean - @$(MAKE) -C $(PROJECT_ROOT)/assets - @$(PROJECT_ROOT)/scripts/assets.py manifest assets/resources + @$(MAKE) -C $(PROJECT_ROOT)/assets manifest + +.PHONY: assets_rebuild +assets_rebuild: + @$(MAKE) -C $(PROJECT_ROOT)/assets clean all .PHONY: flash_radio flash_radio: @@ -124,8 +125,8 @@ flash_radio_fus: .PHONY: flash_radio_fus_please_i_m_not_going_to_complain flash_radio_fus_please_i_m_not_going_to_complain: - @$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin - @$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw.bin + @$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin + @$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw.bin @$(PROJECT_ROOT)/scripts/ob.py set .PHONY: lint diff --git a/applications/updater/util/update_task.c b/applications/updater/util/update_task.c index 04405bcf..197d42f5 100644 --- a/applications/updater/util/update_task.c +++ b/applications/updater/util/update_task.c @@ -19,7 +19,7 @@ static const char* update_task_stage_descr[] = { [UpdateTaskStageRadioCommit] = "Applying radio stack", [UpdateTaskStageLfsBackup] = "Backing up LFS", [UpdateTaskStageLfsRestore] = "Restoring LFS", - [UpdateTaskStageAssetsUpdate] = "Updating assets", + [UpdateTaskStageResourcesUpdate] = "Updating resources", [UpdateTaskStageCompleted] = "Completed!", [UpdateTaskStageError] = "Error", }; diff --git a/applications/updater/util/update_task.h b/applications/updater/util/update_task.h index 25650de8..2325824c 100644 --- a/applications/updater/util/update_task.h +++ b/applications/updater/util/update_task.h @@ -23,7 +23,7 @@ typedef enum { UpdateTaskStageRadioCommit, UpdateTaskStageLfsBackup, UpdateTaskStageLfsRestore, - UpdateTaskStageAssetsUpdate, + UpdateTaskStageResourcesUpdate, UpdateTaskStageCompleted, UpdateTaskStageError, } UpdateTaskStage; diff --git a/applications/updater/util/update_task_workers.c b/applications/updater/util/update_task_workers.c index 2a22692b..d0abbc18 100644 --- a/applications/updater/util/update_task_workers.c +++ b/applications/updater/util/update_task_workers.c @@ -166,14 +166,13 @@ static bool update_task_post_update(UpdateTask* update_task) { .total_files = 0, .processed_files = 0, }; - update_task_set_progress(update_task, UpdateTaskStageAssetsUpdate, 0); + update_task_set_progress(update_task, UpdateTaskStageResourcesUpdate, 0); path_concat( string_get_cstr(update_task->update_path), string_get_cstr(update_task->manifest->resource_bundle), file_path); - update_task_set_progress(update_task, UpdateTaskStageProgress, 0); TarArchive* archive = tar_archive_alloc(update_task->storage); tar_archive_set_file_callback(archive, update_task_resource_unpack_cb, &progress); success = tar_archive_open(archive, string_get_cstr(file_path), TAR_OPEN_MODE_READ); diff --git a/assets/.gitignore b/assets/.gitignore index 3f30e227..0a0acede 100644 --- a/assets/.gitignore +++ b/assets/.gitignore @@ -1 +1 @@ -/headers \ No newline at end of file +/headers diff --git a/assets/Makefile b/assets/Makefile index 91cc0671..19d148fd 100644 --- a/assets/Makefile +++ b/assets/Makefile @@ -3,11 +3,11 @@ PROJECT_ROOT = $(abspath $(dir $(abspath $(firstword $(MAKEFILE_LIST))))..) include $(PROJECT_ROOT)/assets/assets.mk .PHONY: all -all: icons protobuf dolphin +all: icons protobuf dolphin manifest -$(ASSETS): $(ASSETS_SOURCES) $(ASSETS_COMPILLER) +$(ASSETS): $(ASSETS_SOURCES) $(ASSETS_COMPILER) @echo "\tASSETS\t\t" $@ - @$(ASSETS_COMPILLER) icons "$(ASSETS_SOURCE_DIR)" "$(ASSETS_COMPILED_DIR)" + @$(ASSETS_COMPILER) icons "$(ASSETS_SOURCE_DIR)" "$(ASSETS_COMPILED_DIR)" .PHONY: icons icons: $(ASSETS) @@ -22,11 +22,15 @@ protobuf: $(PROTOBUF) $(DOLPHIN_EXTERNAL_OUTPUT_DIR): $(DOLPHIN_SOURCE_DIR) @echo "\tDOLPHIN blocking" - @$(ASSETS_COMPILLER) dolphin -s dolphin_blocking "$(DOLPHIN_SOURCE_DIR)/blocking" "$(DOLPHIN_INTERNAL_OUTPUT_DIR)" + @$(ASSETS_COMPILER) dolphin -s dolphin_blocking "$(DOLPHIN_SOURCE_DIR)/blocking" "$(DOLPHIN_INTERNAL_OUTPUT_DIR)" @echo "\tDOLPHIN internal" - @$(ASSETS_COMPILLER) dolphin -s dolphin_internal "$(DOLPHIN_SOURCE_DIR)/internal" "$(DOLPHIN_INTERNAL_OUTPUT_DIR)" + @$(ASSETS_COMPILER) dolphin -s dolphin_internal "$(DOLPHIN_SOURCE_DIR)/internal" "$(DOLPHIN_INTERNAL_OUTPUT_DIR)" @echo "\tDOLPHIN external" - @$(ASSETS_COMPILLER) dolphin "$(DOLPHIN_SOURCE_DIR)/external" "$(DOLPHIN_EXTERNAL_OUTPUT_DIR)" + @$(ASSETS_COMPILER) dolphin "$(DOLPHIN_SOURCE_DIR)/external" "$(DOLPHIN_EXTERNAL_OUTPUT_DIR)" + +.PHONY: manifest +manifest: + $(ASSETS_COMPILER) manifest $(RESOURCES_DIR) .PHONY: dolphin dolphin: $(DOLPHIN_EXTERNAL_OUTPUT_DIR) diff --git a/assets/assets.mk b/assets/assets.mk index 55783ec8..18e0a244 100644 --- a/assets/assets.mk +++ b/assets/assets.mk @@ -1,11 +1,15 @@ ASSETS_DIR := $(PROJECT_ROOT)/assets -ASSETS_COMPILLER := $(PROJECT_ROOT)/scripts/assets.py +ASSETS_COMPILER := $(PROJECT_ROOT)/scripts/assets.py ASSETS_COMPILED_DIR := $(ASSETS_DIR)/compiled ASSETS_SOURCE_DIR := $(ASSETS_DIR)/icons ASSETS_SOURCES += $(shell find $(ASSETS_SOURCE_DIR) -type f -iname '*.png' -or -iname 'frame_rate') ASSETS += $(ASSETS_COMPILED_DIR)/assets_icons.c +RESOURCES_DIR := $(ASSETS_DIR)/resources +RESOURCES_MANIFEST := $(RESOURCES_DIR)/Manifest +RESOURCES_FILES := $(shell find $(RESOURCES_DIR) ! -name Manifest -type f) + DOLPHIN_SOURCE_DIR := $(ASSETS_DIR)/dolphin DOLPHIN_INTERNAL_OUTPUT_DIR := $(ASSETS_COMPILED_DIR) DOLPHIN_EXTERNAL_OUTPUT_DIR := $(ASSETS_DIR)/resources/dolphin diff --git a/assets/resources/Manifest b/assets/resources/Manifest new file mode 100644 index 00000000..12773c00 --- /dev/null +++ b/assets/resources/Manifest @@ -0,0 +1,240 @@ +V:0 +T:1650389893 +D:badusb +D:dolphin +D:infrared +D:nfc +D:subghz +D:u2f +F:bb8ffef2d052f171760ce3dc5220cbad:1591:badusb/demo_macos.txt +F:e538ad2ce5a06ec45e1b5b24824901b1:1552:badusb/demo_windows.txt +D:dolphin/L1_Boxing_128x64 +D:dolphin/L1_Cry_128x64 +D:dolphin/L1_Furippa1_128x64 +D:dolphin/L1_Laptop_128x51 +D:dolphin/L1_Leaving_sad_128x64 +D:dolphin/L1_Mad_fist_128x64 +D:dolphin/L1_Read_books_128x64 +D:dolphin/L1_Recording_128x51 +D:dolphin/L1_Sleep_128x64 +D:dolphin/L1_Waves_128x50 +D:dolphin/L2_Furippa2_128x64 +D:dolphin/L2_Hacking_pc_128x64 +D:dolphin/L2_Soldering_128x64 +D:dolphin/L3_Furippa3_128x64 +D:dolphin/L3_Hijack_radio_128x64 +D:dolphin/L3_Lab_research_128x54 +F:d1148ab5354eaf4fa7f959589d840932:1563:dolphin/manifest.txt +F:d37be8444102ec5cde5fe3a85d55b57d:481:dolphin/L1_Boxing_128x64/frame_0.bm +F:54fb07443bc153ded9589b74d23b4263:461:dolphin/L1_Boxing_128x64/frame_1.bm +F:e007afe130d699c715b99ce8e5b407bd:531:dolphin/L1_Boxing_128x64/frame_2.bm +F:a999a9a6c76c66158f1aa5ccb56de7c9:437:dolphin/L1_Boxing_128x64/frame_3.bm +F:ec6af9cb451ab16c0fa62e95e8134b49:459:dolphin/L1_Boxing_128x64/frame_4.bm +F:2aa0c1e7bf1131b9dc172aa595ec01f2:450:dolphin/L1_Boxing_128x64/frame_5.bm +F:bbc8f750d17d156438c5cfe1122ec7f4:442:dolphin/L1_Boxing_128x64/frame_6.bm +F:f6e51ada3e3285e330714dab5b4277dd:418:dolphin/L1_Boxing_128x64/meta.txt +F:ab33a6f37209541f3db938d1cfe1706f:889:dolphin/L1_Cry_128x64/frame_0.bm +F:1b3fdeb404af0f7402caa5a5e091a8f8:911:dolphin/L1_Cry_128x64/frame_1.bm +F:4db644b173af72f3d371d2bd81f76b05:910:dolphin/L1_Cry_128x64/frame_2.bm +F:cd4c0ef67a8e514edecd9600242db068:923:dolphin/L1_Cry_128x64/frame_3.bm +F:ee02e9589e0714d3e2bc0d93aa294ccb:894:dolphin/L1_Cry_128x64/frame_4.bm +F:7703a7d9745d13b45d73ce4b86b4cdc8:940:dolphin/L1_Cry_128x64/frame_5.bm +F:ee6de6a0ed903317c4948cb445e0a9a8:915:dolphin/L1_Cry_128x64/frame_6.bm +F:a3892e45826c66f48d3d64fb81521446:934:dolphin/L1_Cry_128x64/frame_7.bm +F:680b12cc4dad722d6583b7e710bfc297:516:dolphin/L1_Cry_128x64/meta.txt +F:4911eaa7cb84ced19e5dea2af51b91a5:294:dolphin/L1_Furippa1_128x64/frame_0.bm +F:5669bee57c7b3d93a1665dd87fd5372a:325:dolphin/L1_Furippa1_128x64/frame_1.bm +F:80b48a77682b853e6236cd1c89083e6f:465:dolphin/L1_Furippa1_128x64/frame_10.bm +F:9d8ea10bf3d3831cb4a94957dc0b41c6:698:dolphin/L1_Furippa1_128x64/frame_11.bm +F:2dbb3125ea63550906fba8f7ec7b1da3:541:dolphin/L1_Furippa1_128x64/frame_12.bm +F:6a06b718957dca9caa63a4f3baa73abb:584:dolphin/L1_Furippa1_128x64/frame_13.bm +F:5450bf16c3d2fceaf5e6ea585b7ef7c1:610:dolphin/L1_Furippa1_128x64/frame_14.bm +F:535c0eca62703eb7df36f17334a6191b:719:dolphin/L1_Furippa1_128x64/frame_15.bm +F:7c03af85ade9b791755f3a4d106c2b7c:458:dolphin/L1_Furippa1_128x64/frame_16.bm +F:41b8fea16ad8705f4594e6119eade395:400:dolphin/L1_Furippa1_128x64/frame_17.bm +F:2db7fd3da5208a8e41902ae27cf41702:333:dolphin/L1_Furippa1_128x64/frame_18.bm +F:7e47428442e0f04959fc6afde979936e:351:dolphin/L1_Furippa1_128x64/frame_2.bm +F:0eb187078f169d7a852e97ecf430aea0:324:dolphin/L1_Furippa1_128x64/frame_3.bm +F:967c402971a442a5bf28eba804bb3ff4:387:dolphin/L1_Furippa1_128x64/frame_4.bm +F:175cb930fba0fc86f54a3a109b741708:390:dolphin/L1_Furippa1_128x64/frame_5.bm +F:f8c3ee1ab657549d1d00c1c72d8d2ff5:407:dolphin/L1_Furippa1_128x64/frame_6.bm +F:4911eaa7cb84ced19e5dea2af51b91a5:294:dolphin/L1_Furippa1_128x64/frame_7.bm +F:8f649ff34b224f4e564644a4494c54ed:283:dolphin/L1_Furippa1_128x64/frame_8.bm +F:3ec3c40d26bf8d3e691b1335d20d4ec0:312:dolphin/L1_Furippa1_128x64/frame_9.bm +F:ebe088426d184cf6651288accd21add6:241:dolphin/L1_Furippa1_128x64/meta.txt +F:d02fdfd1a3b89da00d2acf32bd09da80:555:dolphin/L1_Laptop_128x51/frame_0.bm +F:7e29ea503d41023fa3895d15458f106d:557:dolphin/L1_Laptop_128x51/frame_1.bm +F:eb55e0629de873f537d8412ced528eb4:560:dolphin/L1_Laptop_128x51/frame_2.bm +F:1516472ab3c140dd5bd4d089caa44747:556:dolphin/L1_Laptop_128x51/frame_3.bm +F:61172f89cf0a17bd7f978edccdeed166:560:dolphin/L1_Laptop_128x51/frame_4.bm +F:9d54913928c7e9477b6b8a43f3767621:554:dolphin/L1_Laptop_128x51/frame_5.bm +F:5243d6272bbb213e9c17af07ee011402:553:dolphin/L1_Laptop_128x51/frame_6.bm +F:aa68e0f28f117891ba0f4d7613224fc6:560:dolphin/L1_Laptop_128x51/frame_7.bm +F:9ef1935ab29fe70bbc517f4b602547d7:403:dolphin/L1_Laptop_128x51/meta.txt +F:6ce34e62c5bf4764a4163101afe63e60:514:dolphin/L1_Leaving_sad_128x64/frame_0.bm +F:19a0e0c518d222d91d24b8712ab6bb80:526:dolphin/L1_Leaving_sad_128x64/frame_1.bm +F:837bfb424c8d8a3bfbda7d6a28ba5a5c:316:dolphin/L1_Leaving_sad_128x64/frame_10.bm +F:1a69b6f63a96e0958837ea8b21db3966:294:dolphin/L1_Leaving_sad_128x64/frame_11.bm +F:c3ea827593a4563d544dfb7e99d73885:322:dolphin/L1_Leaving_sad_128x64/frame_12.bm +F:1e3842669191fe9599f830ac133e0751:542:dolphin/L1_Leaving_sad_128x64/frame_2.bm +F:9161660e6827bd776a15eefa2a8add19:557:dolphin/L1_Leaving_sad_128x64/frame_3.bm +F:d01a79fdb4f84397d82bf9927aeb71e0:488:dolphin/L1_Leaving_sad_128x64/frame_4.bm +F:316e30ef319c080fab2a79c21e526319:469:dolphin/L1_Leaving_sad_128x64/frame_5.bm +F:09a812d59b60b5fe7724057daa14ad60:499:dolphin/L1_Leaving_sad_128x64/frame_6.bm +F:9eb07b76cc864a0ce2918d68e41d4500:486:dolphin/L1_Leaving_sad_128x64/frame_7.bm +F:cf8c4cc4abbd700b096037b7ebfd0e31:403:dolphin/L1_Leaving_sad_128x64/frame_8.bm +F:889728ded689203aa82193e573912d18:317:dolphin/L1_Leaving_sad_128x64/frame_9.bm +F:2bff1f09ad1e9059a60e08990ca1d414:477:dolphin/L1_Leaving_sad_128x64/meta.txt +F:c31a882e95ed5c69fd63226db2188710:520:dolphin/L1_Mad_fist_128x64/frame_0.bm +F:740326828f6ba6e29373943ba835e77f:540:dolphin/L1_Mad_fist_128x64/frame_1.bm +F:0c9693dda040fd73ca6d773a10924bd8:542:dolphin/L1_Mad_fist_128x64/frame_10.bm +F:425c1d101debd1e9502db2628640b704:505:dolphin/L1_Mad_fist_128x64/frame_11.bm +F:aa576f7dbd14ec682f6c50314165fb14:501:dolphin/L1_Mad_fist_128x64/frame_12.bm +F:712335eabefb8c7bb7fb2f4301419c10:500:dolphin/L1_Mad_fist_128x64/frame_13.bm +F:b6e11711ea4dcc2e64f267d888f91baf:515:dolphin/L1_Mad_fist_128x64/frame_2.bm +F:61bdd22a2b1e67efe093b6acf7dfadce:538:dolphin/L1_Mad_fist_128x64/frame_3.bm +F:20ae06a3ce7a07656e578edb024e2b3f:512:dolphin/L1_Mad_fist_128x64/frame_4.bm +F:45cf2bd55365a7328df39fe98a496cc9:519:dolphin/L1_Mad_fist_128x64/frame_5.bm +F:4b8840eebb3a4a1ead69a7130816047e:524:dolphin/L1_Mad_fist_128x64/frame_6.bm +F:0de4497a5fbf80cc93e523465c5e3122:515:dolphin/L1_Mad_fist_128x64/frame_7.bm +F:32d8ddeb19bfa415fe283666b1e323a2:517:dolphin/L1_Mad_fist_128x64/frame_8.bm +F:a42a0578c2d0411500fb3485a3beb536:526:dolphin/L1_Mad_fist_128x64/frame_9.bm +F:10a521c78168a5928c859494e2a61cd2:349:dolphin/L1_Mad_fist_128x64/meta.txt +F:61565b7be9a69a60ce2dbae0273df347:653:dolphin/L1_Read_books_128x64/frame_0.bm +F:cf5a2d423540e3af37e789d70c9c1fbf:653:dolphin/L1_Read_books_128x64/frame_1.bm +F:c91935861979d024e6637b8810889878:650:dolphin/L1_Read_books_128x64/frame_2.bm +F:0c007a30f396f3e7a0ded2b24080357d:646:dolphin/L1_Read_books_128x64/frame_3.bm +F:323a52816dd79d6d3186f451e26e06ad:650:dolphin/L1_Read_books_128x64/frame_4.bm +F:494f27958f4cea9b94d09cf27725c5cd:652:dolphin/L1_Read_books_128x64/frame_5.bm +F:a6a7491fe80255e1745c9f293da52805:646:dolphin/L1_Read_books_128x64/frame_6.bm +F:238497e6643fd491cd6002e98c615c05:647:dolphin/L1_Read_books_128x64/frame_7.bm +F:300651e8f53d9a29ae38d4b9292c73cf:643:dolphin/L1_Read_books_128x64/frame_8.bm +F:3d9568deeff646b677092902a98f9ceb:325:dolphin/L1_Read_books_128x64/meta.txt +F:2aba555567ab70cff003ded4138c6721:663:dolphin/L1_Recording_128x51/frame_0.bm +F:8456c6e86825957e5662e2f08eb6c116:657:dolphin/L1_Recording_128x51/frame_1.bm +F:2e4a1aca5afa5a6ab254884210875eb4:629:dolphin/L1_Recording_128x51/frame_10.bm +F:9f1cf96598e3d935879b1d0c97705778:659:dolphin/L1_Recording_128x51/frame_11.bm +F:409abfeca974e5649affcd1faafea988:628:dolphin/L1_Recording_128x51/frame_2.bm +F:66b2a5abf05acbf79f9943e01b8b8cec:654:dolphin/L1_Recording_128x51/frame_3.bm +F:d55c5ed28c2ff48f42ab30b420d64fa3:662:dolphin/L1_Recording_128x51/frame_4.bm +F:2ce12d8cfdd953c9dadb9459c580a320:622:dolphin/L1_Recording_128x51/frame_5.bm +F:da631e3837fcdf3ee9e6abdf17fb764b:664:dolphin/L1_Recording_128x51/frame_6.bm +F:604a7cdac2491c9bc2e88b9e91c99dcc:626:dolphin/L1_Recording_128x51/frame_7.bm +F:fc94649dc98244dd9a0ab7fe62721d3c:663:dolphin/L1_Recording_128x51/frame_8.bm +F:b2475ab8ee26cbd9a403ee603520bd35:661:dolphin/L1_Recording_128x51/frame_9.bm +F:a7c2b3b420706712149cc2426c68df4f:219:dolphin/L1_Recording_128x51/meta.txt +F:9858fd34b55cebcb9be50c5710212a13:580:dolphin/L1_Sleep_128x64/frame_0.bm +F:e47ef8c846083b8fde028b1724861444:589:dolphin/L1_Sleep_128x64/frame_1.bm +F:9749bd05b47fd07cc3a41ab201f86bf4:582:dolphin/L1_Sleep_128x64/frame_2.bm +F:edf11266b20b846ace622e41cd36906b:597:dolphin/L1_Sleep_128x64/frame_3.bm +F:8fbb96a9d809d85fa6bad931fe4e6fe2:510:dolphin/L1_Sleep_128x64/meta.txt +F:283b41f1b2c581c510ff176293b7288a:443:dolphin/L1_Waves_128x50/frame_0.bm +F:c9fc5127e1d8a4217b6b177716725ba0:448:dolphin/L1_Waves_128x50/frame_1.bm +F:8e0797bf26d5d8d3cbeb99798c222b80:463:dolphin/L1_Waves_128x50/frame_2.bm +F:da02b1deb3119b31f2b8f182d5bf3242:472:dolphin/L1_Waves_128x50/frame_3.bm +F:8e6fb4133acbda7e5bb9adad0aed306c:620:dolphin/L1_Waves_128x50/meta.txt +F:be80d2fa903e3250b69c063a1eef0621:350:dolphin/L2_Furippa2_128x64/frame_0.bm +F:9e628f5e154f12d6c57b13befed1f5f6:385:dolphin/L2_Furippa2_128x64/frame_1.bm +F:80b48a77682b853e6236cd1c89083e6f:465:dolphin/L2_Furippa2_128x64/frame_10.bm +F:9d8ea10bf3d3831cb4a94957dc0b41c6:698:dolphin/L2_Furippa2_128x64/frame_11.bm +F:2dbb3125ea63550906fba8f7ec7b1da3:541:dolphin/L2_Furippa2_128x64/frame_12.bm +F:6a06b718957dca9caa63a4f3baa73abb:584:dolphin/L2_Furippa2_128x64/frame_13.bm +F:5450bf16c3d2fceaf5e6ea585b7ef7c1:610:dolphin/L2_Furippa2_128x64/frame_14.bm +F:e3c92103f403857b502081d3b058e53a:740:dolphin/L2_Furippa2_128x64/frame_15.bm +F:432669d796bbf7be1d14f5b7db036a92:533:dolphin/L2_Furippa2_128x64/frame_16.bm +F:53485c6b465c80a1ce8ddf03c4976039:451:dolphin/L2_Furippa2_128x64/frame_17.bm +F:333b75b16c088428a28259c931630fb9:397:dolphin/L2_Furippa2_128x64/frame_18.bm +F:ed02d68380382361f3f01cbf01d13b0c:402:dolphin/L2_Furippa2_128x64/frame_2.bm +F:b0ba042d7b60dc5681182b1d4005f0a2:374:dolphin/L2_Furippa2_128x64/frame_3.bm +F:518a84fa5a4e9e7f84246d5d82e87f15:440:dolphin/L2_Furippa2_128x64/frame_4.bm +F:9b7b0ae6f4f55d30cb43b0465216aa25:449:dolphin/L2_Furippa2_128x64/frame_5.bm +F:03b153949b0dae2efe1fc5f0dc57a0ef:466:dolphin/L2_Furippa2_128x64/frame_6.bm +F:be80d2fa903e3250b69c063a1eef0621:350:dolphin/L2_Furippa2_128x64/frame_7.bm +F:a8433f451cf3efc4ce2fb04a38c1f84f:319:dolphin/L2_Furippa2_128x64/frame_8.bm +F:d32a11bf9779d57191c1e59fe69cf83d:317:dolphin/L2_Furippa2_128x64/frame_9.bm +F:ebe088426d184cf6651288accd21add6:241:dolphin/L2_Furippa2_128x64/meta.txt +F:af4ec0085c29732085c51b18dc97bc27:543:dolphin/L2_Hacking_pc_128x64/frame_0.bm +F:eb141965fb6fb9f8b28766bac92abe1a:545:dolphin/L2_Hacking_pc_128x64/frame_1.bm +F:f7b33d3541dab08aaf4e8375e262b982:548:dolphin/L2_Hacking_pc_128x64/frame_2.bm +F:03634d90c54fd235aa76c0f9f794c80b:608:dolphin/L2_Hacking_pc_128x64/frame_3.bm +F:4c77406302f3fb74f8bdba568097082a:609:dolphin/L2_Hacking_pc_128x64/frame_4.bm +F:b0d1783358094534ac95b3455124d5fe:409:dolphin/L2_Hacking_pc_128x64/meta.txt +F:584c92e6fb15e99389b84d567e6d4d02:699:dolphin/L2_Soldering_128x64/frame_0.bm +F:3fa01b93460379204b6d14f43573b4f3:688:dolphin/L2_Soldering_128x64/frame_1.bm +F:6fad29757d4b7231b1d0ec53d0529b45:699:dolphin/L2_Soldering_128x64/frame_10.bm +F:e82c83e5a03abf4f6a1efd0a0f1ca33a:689:dolphin/L2_Soldering_128x64/frame_2.bm +F:7f9f310e22ef85af225dd1aefa2c47ba:689:dolphin/L2_Soldering_128x64/frame_3.bm +F:1ff31af6f90f07c0cdfa3283f52a5adc:693:dolphin/L2_Soldering_128x64/frame_4.bm +F:1a8f25aff949860cc6ffc79b4f48d5dd:696:dolphin/L2_Soldering_128x64/frame_5.bm +F:dbaa75feb8aebaf9b1cc5201c29952b8:712:dolphin/L2_Soldering_128x64/frame_6.bm +F:ee356bd981fba90c402d8e08d3015792:732:dolphin/L2_Soldering_128x64/frame_7.bm +F:09d5c5a685df606562d407bb9dac798e:705:dolphin/L2_Soldering_128x64/frame_8.bm +F:5451816e73bad029b3b9f3f55d294582:698:dolphin/L2_Soldering_128x64/frame_9.bm +F:c38ffad11987faf5ba6e363ead705e78:319:dolphin/L2_Soldering_128x64/meta.txt +F:2e083023ab65d1f99bba71f9aae6db9a:398:dolphin/L3_Furippa3_128x64/frame_0.bm +F:8cf20e07d84fd6a1157ba932beca70ea:438:dolphin/L3_Furippa3_128x64/frame_1.bm +F:018344c951691b7b1d77c1c6729d3e42:559:dolphin/L3_Furippa3_128x64/frame_10.bm +F:07008e2508064ab7a8467802472a9803:728:dolphin/L3_Furippa3_128x64/frame_11.bm +F:2dbb3125ea63550906fba8f7ec7b1da3:541:dolphin/L3_Furippa3_128x64/frame_12.bm +F:6a06b718957dca9caa63a4f3baa73abb:584:dolphin/L3_Furippa3_128x64/frame_13.bm +F:5450bf16c3d2fceaf5e6ea585b7ef7c1:610:dolphin/L3_Furippa3_128x64/frame_14.bm +F:e333224a4bed87b606df57a252ed4887:741:dolphin/L3_Furippa3_128x64/frame_15.bm +F:a20a6abfbd66fc3f92c66adacc4444a3:559:dolphin/L3_Furippa3_128x64/frame_16.bm +F:c1e051dce6b90e4f69b4792d0356a6b3:492:dolphin/L3_Furippa3_128x64/frame_17.bm +F:377f3621507c6590120cbc1c8ca92999:445:dolphin/L3_Furippa3_128x64/frame_18.bm +F:81f09c0fcd2bddb8a107a199e7149230:463:dolphin/L3_Furippa3_128x64/frame_2.bm +F:ed7fd1ada1070493462c1899f7372baf:424:dolphin/L3_Furippa3_128x64/frame_3.bm +F:e5fb2cdc4e08d6abff3191d37a1007ed:499:dolphin/L3_Furippa3_128x64/frame_4.bm +F:923a05250e5a93c7db7bbbf48448d164:504:dolphin/L3_Furippa3_128x64/frame_5.bm +F:1e9628db28a9a908c4a4b24cb16c5d20:521:dolphin/L3_Furippa3_128x64/frame_6.bm +F:2e083023ab65d1f99bba71f9aae6db9a:398:dolphin/L3_Furippa3_128x64/frame_7.bm +F:f1ec6e12daba9490f9e2e0e308ae3f83:419:dolphin/L3_Furippa3_128x64/frame_8.bm +F:106997120ad4cd23bd51e6f26bd7d74d:435:dolphin/L3_Furippa3_128x64/frame_9.bm +F:ebe088426d184cf6651288accd21add6:241:dolphin/L3_Furippa3_128x64/meta.txt +F:42970030123b2468984785fea7c60318:524:dolphin/L3_Hijack_radio_128x64/frame_0.bm +F:491c6d8ef21e48ca0f6b5fbd269c820b:527:dolphin/L3_Hijack_radio_128x64/frame_1.bm +F:ff499c8716c5f7fc1110a5ee82bda20c:550:dolphin/L3_Hijack_radio_128x64/frame_10.bm +F:ee39d82d6efc6a6992d19b6d75a6c509:572:dolphin/L3_Hijack_radio_128x64/frame_11.bm +F:5d14e8cb9d67bf8f597d6c749d07a135:539:dolphin/L3_Hijack_radio_128x64/frame_12.bm +F:9461004b75a34a36097668159c4cabe6:579:dolphin/L3_Hijack_radio_128x64/frame_13.bm +F:c925d4b1dff9c81463944cf930d7da8d:526:dolphin/L3_Hijack_radio_128x64/frame_2.bm +F:f98ed80cfab3a94b580be81654401c89:529:dolphin/L3_Hijack_radio_128x64/frame_3.bm +F:97ba548c27732be9e05fb8f7be8204ce:571:dolphin/L3_Hijack_radio_128x64/frame_4.bm +F:524932eb2391057fc1dea7237c7086e3:574:dolphin/L3_Hijack_radio_128x64/frame_5.bm +F:8eb9672f719926ac9c4c158575f388cd:524:dolphin/L3_Hijack_radio_128x64/frame_6.bm +F:7ca93fbab93bc278d4a11089d624a07b:655:dolphin/L3_Hijack_radio_128x64/frame_7.bm +F:37b4368f0b7235f3a7347bf499541666:645:dolphin/L3_Hijack_radio_128x64/frame_8.bm +F:ea9c3d7bab4756c2916369d5e130fa71:611:dolphin/L3_Hijack_radio_128x64/frame_9.bm +F:8583743f18a12ff647d3478e7aebdad6:230:dolphin/L3_Hijack_radio_128x64/meta.txt +F:f5f02a9df03bba734bdb7ed3297795f0:611:dolphin/L3_Lab_research_128x54/frame_0.bm +F:8f9655ad286464159443922d00e45620:614:dolphin/L3_Lab_research_128x54/frame_1.bm +F:7793b1bc107d4ea2e311e92dc16bf946:576:dolphin/L3_Lab_research_128x54/frame_10.bm +F:f24b8409f9dc770f3845424fe0ab489e:585:dolphin/L3_Lab_research_128x54/frame_11.bm +F:4ea93c4482dac43f40b67cc308f21e6d:571:dolphin/L3_Lab_research_128x54/frame_12.bm +F:cf3bb68dc78c568db22f37057a9fdd66:615:dolphin/L3_Lab_research_128x54/frame_13.bm +F:79719219aaebc95ea525def9173cabf5:618:dolphin/L3_Lab_research_128x54/frame_2.bm +F:05572cfd756704acd6ce9d6c15d03fc0:608:dolphin/L3_Lab_research_128x54/frame_3.bm +F:a26604a0d5427d5cf62a7a911a68b16c:615:dolphin/L3_Lab_research_128x54/frame_4.bm +F:9edc345fe53017970f93dc680818e63e:618:dolphin/L3_Lab_research_128x54/frame_5.bm +F:cf3bb68dc78c568db22f37057a9fdd66:615:dolphin/L3_Lab_research_128x54/frame_6.bm +F:5442895c85f769349288aa3df0990f9d:585:dolphin/L3_Lab_research_128x54/frame_7.bm +F:33b8fde22f34ef556b64b77164bc19b0:578:dolphin/L3_Lab_research_128x54/frame_8.bm +F:f267f0654781049ca323b11bb4375519:581:dolphin/L3_Lab_research_128x54/frame_9.bm +F:41106c0cbc5144f151b2b2d3daaa0527:727:dolphin/L3_Lab_research_128x54/meta.txt +D:infrared/assets +F:5b16e1a59daf3ef1d0fc95b3b5596d67:74300:infrared/assets/tv.ir +D:nfc/assets +F:c6826a621d081d68309e4be424d3d974:4715:nfc/assets/aid.nfc +F:86efbebdf41bb6bf15cc51ef88f069d5:2565:nfc/assets/country_code.nfc +F:41b4f08774249014cb8d3dffa5f5c07d:1757:nfc/assets/currency_code.nfc +F:c60e862919731b0bd538a1001bbc1098:17453:nfc/assets/mf_classic_dict.nfc +D:subghz/assets +F:dda1ef895b8a25fde57c874feaaef997:650:subghz/assets/came_atomo +F:610a0ffa2479a874f2060eb2348104c5:2712:subghz/assets/keeloq_mfcodes +F:9214f9c10463b746a27e82ce0b96e040:465:subghz/assets/keeloq_mfcodes_user +F:653bd8d349055a41e1152e557d4a52d3:202:subghz/assets/nice_flor_s +F:00e967e5c558e44a0651bb821d5cf1d0:414:subghz/assets/setting_frequency_analyzer_user +F:16e8c7cb4a13f26ea55b2b0a59f9cc7a:554:subghz/assets/setting_user +D:u2f/assets +F:7e11e688e39034bbb9d88410044795e1:365:u2f/assets/cert.der +F:f60b88c20ed479ed9684e249f7134618:264:u2f/assets/cert_key.u2f diff --git a/lib/update_util/update_manifest.c b/lib/update_util/update_manifest.c index 5ec942c8..3d9ec9c3 100644 --- a/lib/update_util/update_manifest.c +++ b/lib/update_util/update_manifest.c @@ -13,7 +13,7 @@ #define MANIFEST_KEY_RADIO_ADDRESS "Radio address" #define MANIFEST_KEY_RADIO_VERSION "Radio version" #define MANIFEST_KEY_RADIO_CRC "Radio CRC" -#define MANIFEST_KEY_ASSETS_FILE "Assets" +#define MANIFEST_KEY_ASSETS_FILE "Resources" UpdateManifest* update_manifest_alloc() { UpdateManifest* update_manifest = malloc(sizeof(UpdateManifest)); diff --git a/make/rules.mk b/make/rules.mk index e907b0eb..32e525b6 100644 --- a/make/rules.mk +++ b/make/rules.mk @@ -86,7 +86,6 @@ $(OBJ_DIR)/upload: $(OBJ_DIR)/$(PROJECT).bin dfu-util -d 0483:df11 -D $(OBJ_DIR)/$(PROJECT).bin -a 0 -s $(FLASH_ADDRESS) $(DFU_OPTIONS) touch $@ - .PHONY: flash flash: $(OBJ_DIR)/flash diff --git a/scripts/assets.py b/scripts/assets.py index 3d455646..bb7b493d 100755 --- a/scripts/assets.py +++ b/scripts/assets.py @@ -203,15 +203,12 @@ class Main(App): manifest_file = os.path.join(directory_path, "Manifest") old_manifest = Manifest() if os.path.exists(manifest_file): - self.logger.info( - f"old manifest is present, loading for compare and removing file" - ) + self.logger.info("old manifest is present, loading for compare") old_manifest.load(manifest_file) - os.unlink(manifest_file) self.logger.info(f'Creating new Manifest for directory "{directory_path}"') new_manifest = Manifest() new_manifest.create(directory_path) - new_manifest.save(manifest_file) + self.logger.info(f"Comparing new manifest with old") only_in_old, changed, only_in_new = Manifest.compare(old_manifest, new_manifest) for record in only_in_old: @@ -220,6 +217,12 @@ class Main(App): self.logger.info(f"Changed: {record}") for record in only_in_new: self.logger.info(f"Only in new: {record}") + if any((only_in_old, changed, only_in_new)): + self.logger.warning("Manifests are different, updating") + new_manifest.save(manifest_file) + else: + self.logger.info("Manifest is up-to-date!") + self.logger.info(f"Complete") return 0 diff --git a/scripts/dist.py b/scripts/dist.py index 541c386e..de1a02c8 100755 --- a/scripts/dist.py +++ b/scripts/dist.py @@ -18,7 +18,7 @@ class Main(App): self.parser_copy.add_argument("-t", dest="target", required=True) self.parser_copy.add_argument("-p", dest="projects", nargs="+", required=True) self.parser_copy.add_argument("-s", dest="suffix", required=True) - self.parser_copy.add_argument("-a", dest="assets", required=False) + self.parser_copy.add_argument("-r", dest="resources", required=False) self.parser_copy.add_argument( "--bundlever", dest="version", @@ -79,16 +79,16 @@ class Main(App): self.args.version, "-t", self.args.target, - "-dfu", + "--dfu", self.get_dist_filepath(self.get_project_filename("firmware", "dfu")), - "-stage", + "--stage", self.get_dist_filepath(self.get_project_filename("updater", "bin")), ] - if self.args.assets: + if self.args.resources: bundle_args.extend( ( - "-a", - self.args.assets, + "-r", + self.args.resources, ) ) self.logger.info( diff --git a/scripts/flash.py b/scripts/flash.py index 170d4311..cc5c5e17 100755 --- a/scripts/flash.py +++ b/scripts/flash.py @@ -8,7 +8,7 @@ import os from flipper.app import App from flipper.cube import CubeProgrammer -STATEMENT = "AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE" +STATEMENT = "AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE" class Main(App): diff --git a/scripts/flipper/assets/manifest.py b/scripts/flipper/assets/manifest.py index c2962e7c..103f07b6 100644 --- a/scripts/flipper/assets/manifest.py +++ b/scripts/flipper/assets/manifest.py @@ -18,10 +18,10 @@ class ManifestRecord: def toLine(self): raise NotImplementedError - def _unpack(self, manifest, key, type): + def _unpack(self, manifest, key, nodetype): key, value = manifest.readline().split(":", 1) assert key == key - return type(value) + return nodetype(value) MANIFEST_TAGS_RECORDS = {} @@ -94,7 +94,7 @@ class ManifestRecordFile(ManifestRecord): @staticmethod def fromLine(line): data = line.split(":", 3) - return ManifestRecordFile(data[2], data[0], data[1]) + return ManifestRecordFile(data[2], data[0], int(data[1])) def toLine(self): return f"{self.tag}:{self.md5}:{self.size}:{self.path}\n" @@ -133,7 +133,7 @@ class Manifest: def addFile(self, path, md5, size): self.records.append(ManifestRecordFile(path, md5, size)) - def create(self, directory_path): + def create(self, directory_path, ignore_files=["Manifest"]): for root, dirs, files in os.walk(directory_path): relative_root = root.replace(directory_path, "", 1) if relative_root.startswith("/"): @@ -141,13 +141,16 @@ class Manifest: # process directories for dir in dirs: relative_dir_path = os.path.join(relative_root, dir) - self.logger.info(f'Adding directory: "{relative_dir_path}"') + self.logger.debug(f'Adding directory: "{relative_dir_path}"') self.addDirectory(relative_dir_path) # Process files for file in files: relative_file_path = os.path.join(relative_root, file) + if file in ignore_files: + self.logger.info(f'Skipping file "{relative_file_path}"') + continue full_file_path = os.path.join(root, file) - self.logger.info(f'Adding file: "{relative_file_path}"') + self.logger.debug(f'Adding file: "{relative_file_path}"') self.addFile( relative_file_path, file_md5(full_file_path), @@ -155,7 +158,7 @@ class Manifest: ) def toFsTree(self): - root = FsNode("", FsNode.Type.Directory) + root = FsNode("", FsNode.NodeType.Directory) for record in self.records: if isinstance(record, ManifestRecordDirectory): root.addDirectory(record.path) diff --git a/scripts/flipper/utils/fstree.py b/scripts/flipper/utils/fstree.py index c42b4aa6..206a1d99 100644 --- a/scripts/flipper/utils/fstree.py +++ b/scripts/flipper/utils/fstree.py @@ -3,13 +3,13 @@ from collections import OrderedDict class FsNode: - class Type(Enum): + class NodeType(Enum): File = 0 Directory = 1 - def __init__(self, name: str, type: "FsNode.Type", **kwargs): + def __init__(self, name: str, nodetype: "FsNode.Type", **kwargs): self.name = name - self.type = type + self.nodetype = nodetype self.data = kwargs self.parent = None self.children = OrderedDict() @@ -25,7 +25,7 @@ class FsNode: parent_node = self.traverse(fragments) if not parent_node: raise Exception(f"No parent node found for: {path}") - parent_node.addChild(FsNode(name, FsNode.Type.Directory)) + parent_node.addChild(FsNode(name, FsNode.NodeType.Directory)) def addFile(self, path, md5, size): fragments = path.split("/") @@ -34,7 +34,7 @@ class FsNode: parent_node = self.traverse(fragments) if not parent_node: raise Exception(f"No parent node found for: {path}") - parent_node.addChild(FsNode(name, FsNode.Type.File, md5=md5, size=size)) + parent_node.addChild(FsNode(name, FsNode.NodeType.File, md5=md5, size=size)) def getChild(self, name): return self.children[name] @@ -58,19 +58,37 @@ class FsNode: def dump(self): ret = {} ret["name"] = (self.name,) - ret["type"] = (self.type,) + ret["type"] = (self.nodetype,) ret["path"] = (self.getPath(),) if len(self.children): ret["children"] = [node.dump() for node in self.children.values()] return ret +def walk_nodes(node: FsNode): + yield node + for child in node.children.values(): + yield from walk_nodes(child) + + +# Returns filenames: [only_in_left], [changed], [only_in_right] def compare_fs_trees(left: FsNode, right: FsNode): # import pprint # pprint.pprint(left.dump()) # pprint.pprint(right.dump()) + left_dict = dict((node.getPath(), node) for node in walk_nodes(left)) + right_dict = dict((node.getPath(), node) for node in walk_nodes(right)) - only_in_left = [] - changed = [] - only_in_right = [] - return [], [], [] + left_names = set(left_dict.keys()) + right_names = set(right_dict.keys()) + common_names = left_names.intersection(right_names) + + return ( + list(left_names - right_names), + list( + name + for name in common_names + if left_dict[name].data != right_dict[name].data + ), + list(right_names - left_names), + ) diff --git a/scripts/update.py b/scripts/update.py index 187c9288..25ae2733 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -10,8 +10,12 @@ import tarfile class Main(App): + UPDATE_MANIFEST_NAME = "update.fuf" + # No compression, plain tar - ASSET_TAR_MODE = "w:" + RESOURCE_TAR_MODE = "w:" + RESOURCE_TAR_FORMAT = tarfile.USTAR_FORMAT + RESOURCE_FILE_NAME = "resources.tar" def init(self): self.subparsers = self.parser.add_subparsers(help="sub-command help") @@ -24,17 +28,17 @@ class Main(App): self.parser_generate.add_argument("-d", dest="directory", required=True) self.parser_generate.add_argument("-v", dest="version", required=True) self.parser_generate.add_argument("-t", dest="target", required=True) - self.parser_generate.add_argument("-dfu", dest="dfu", required=False) - self.parser_generate.add_argument("-a", dest="assets", required=False) - self.parser_generate.add_argument("-stage", dest="stage", required=True) + self.parser_generate.add_argument("--dfu", dest="dfu", required=False) + self.parser_generate.add_argument("-r", dest="resources", required=False) + self.parser_generate.add_argument("--stage", dest="stage", required=True) self.parser_generate.add_argument( - "-radio", dest="radiobin", default="", required=False + "--radio", dest="radiobin", default="", required=False ) self.parser_generate.add_argument( - "-radioaddr", dest="radioaddr", required=False + "--radioaddr", dest="radioaddr", required=False ) self.parser_generate.add_argument( - "-radiover", dest="radioversion", required=False + "--radiover", dest="radioversion", required=False ) self.parser_generate.set_defaults(func=self.generate) @@ -43,7 +47,7 @@ class Main(App): stage_basename = basename(self.args.stage) dfu_basename = basename(self.args.dfu) radiobin_basename = basename(self.args.radiobin) - assets_basename = "" + resources_basename = "" if not exists(self.args.directory): os.makedirs(self.args.directory) @@ -54,10 +58,10 @@ class Main(App): shutil.copyfile( self.args.radiobin, join(self.args.directory, radiobin_basename) ) - if self.args.assets: - assets_basename = "assets.tar" - self.package_assets( - self.args.assets, join(self.args.directory, assets_basename) + if self.args.resources: + resources_basename = self.RESOURCE_FILE_NAME + self.package_resources( + self.args.resources, join(self.args.directory, resources_basename) ) file = FlipperFormatFile() @@ -75,14 +79,14 @@ class Main(App): file.writeKey("Radio CRC", self.int2ffhex(self.crc(self.args.radiobin))) else: file.writeKey("Radio CRC", self.int2ffhex(0)) - file.writeKey("Assets", assets_basename) - file.save(join(self.args.directory, "update.fuf")) + file.writeKey("Resources", resources_basename) + file.save(join(self.args.directory, self.UPDATE_MANIFEST_NAME)) return 0 - def package_assets(self, srcdir: str, dst_name: str): + def package_resources(self, srcdir: str, dst_name: str): with tarfile.open( - dst_name, self.ASSET_TAR_MODE, format=tarfile.USTAR_FORMAT + dst_name, self.RESOURCE_TAR_MODE, format=self.RESOURCE_TAR_FORMAT ) as tarball: tarball.add(srcdir, arcname="")