Skip to content

Commit 8132f05

Browse files
committed
feat: add rudimentary conflict management
1 parent 44e8a63 commit 8132f05

File tree

10 files changed

+187
-86
lines changed

10 files changed

+187
-86
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ index.android.bundle
2323
*.app
2424
*.DSYM.zip
2525
**/metrics/
26+
package/shared-native/.sync-state/

examples/ExpoMessaging/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "1.0.0",
44
"main": "expo-router/entry",
55
"scripts": {
6-
"sync-native": "bash ../../package/scripts/sync-shimmer-from-package.sh expo-package && bash ../../package/scripts/sync-shimmer-native.sh expo-package",
6+
"sync-native": "bash ../../package/scripts/reconcile-shared-native.sh expo-package && bash ../../package/scripts/sync-shared-native.sh expo-package",
77
"prestart": "yarn sync-native",
88
"preandroid": "yarn sync-native",
99
"preios": "yarn sync-native",

examples/SampleApp/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"url": "https://github.com/GetStream/stream-chat-react-native.git"
88
},
99
"scripts": {
10-
"sync-native": "bash ../../package/scripts/sync-shimmer-from-package.sh native-package && bash ../../package/scripts/sync-shimmer-native.sh native-package",
10+
"sync-native": "bash ../../package/scripts/reconcile-shared-native.sh native-package && bash ../../package/scripts/sync-shared-native.sh native-package",
1111
"preandroid": "yarn sync-native",
1212
"android": "react-native run-android",
1313
"preios": "yarn sync-native",

package/expo-package/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@
8282
"expo-audio": "~0.4.6"
8383
},
8484
"scripts": {
85-
"postinstall": "if [ -f ../scripts/sync-shimmer-native.sh ] && [ -d ../shared-native/ios ]; then bash ../scripts/sync-shimmer-native.sh expo-package; fi",
86-
"prepack": "bash ../scripts/sync-shimmer-native.sh expo-package && cp ../../README.md .",
87-
"postpack": "rm README.md && bash ../scripts/clean-shimmer-native-copies.sh expo-package"
85+
"postinstall": "if [ -f ../scripts/sync-shared-native.sh ] && [ -d ../shared-native/ios ]; then bash ../scripts/sync-shared-native.sh expo-package; fi",
86+
"prepack": "bash ../scripts/sync-shared-native.sh expo-package && cp ../../README.md .",
87+
"postpack": "rm README.md && bash ../scripts/clean-shared-native-copies.sh expo-package"
8888
},
8989
"codegenConfig": {
9090
"name": "StreamChatExpoSpec",

package/native-package/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@
8181
}
8282
},
8383
"scripts": {
84-
"postinstall": "if [ -f ../scripts/sync-shimmer-native.sh ] && [ -d ../shared-native/ios ]; then bash ../scripts/sync-shimmer-native.sh native-package; fi",
85-
"prepack": "bash ../scripts/sync-shimmer-native.sh native-package && cp ../../README.md .",
86-
"postpack": "rm README.md && bash ../scripts/clean-shimmer-native-copies.sh native-package"
84+
"postinstall": "if [ -f ../scripts/sync-shared-native.sh ] && [ -d ../shared-native/ios ]; then bash ../scripts/sync-shared-native.sh native-package; fi",
85+
"prepack": "bash ../scripts/sync-shared-native.sh native-package && cp ../../README.md .",
86+
"postpack": "rm README.md && bash ../scripts/clean-shared-native-copies.sh native-package"
8787
},
8888
"devDependencies": {
8989
"react-native": "^0.79.3"

package/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
],
2525
"scripts": {
2626
"install-all": "(yarn install --force && (cd native-package && yarn install --force) && (cd expo-package && yarn install --force))",
27-
"shimmer:sync": "bash ./scripts/sync-shimmer-native.sh all",
28-
"shimmer:clean-copies": "bash ./scripts/clean-shimmer-native-copies.sh all",
27+
"shared-native:sync": "bash ./scripts/sync-shared-native.sh all",
28+
"shared-native:clean-copies": "bash ./scripts/clean-shared-native-copies.sh all",
2929
"build": "rimraf lib && yarn run --silent build-translations && bob build && yarn run --silent copy-translations",
3030
"build-translations": "i18next-cli sync",
3131
"copy-translations": "echo '\u001b[34mℹ\u001b[0m Copying translation files to \u001b[34mlib/typescript/i18n\u001b[0m' && cp -R -f ./src/i18n ./lib/typescript/i18n && echo '\u001b[32m✓\u001b[0m Done Copying Translations'",

package/scripts/clean-shimmer-native-copies.sh renamed to package/scripts/clean-shared-native-copies.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ case "$TARGET" in
3232
;;
3333
esac
3434

35-
echo "Cleaned generated shimmer native copies for target: $TARGET"
35+
echo "Cleaned generated shared native copies for target: $TARGET"
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
TARGET="${1:-all}"
6+
7+
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
8+
STATE_DIR="$ROOT_DIR/shared-native/.sync-state"
9+
SHARED_ANDROID_DIR="$ROOT_DIR/shared-native/android"
10+
SHARED_IOS_DIR="$ROOT_DIR/shared-native/ios"
11+
12+
sync_dir_contents() {
13+
local src_dir="$1"
14+
local dst_dir="$2"
15+
16+
mkdir -p "$dst_dir"
17+
18+
if command -v rsync >/dev/null 2>&1; then
19+
rsync -a --delete "$src_dir"/ "$dst_dir"/
20+
else
21+
find "$dst_dir" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
22+
cp -R "$src_dir"/. "$dst_dir"/
23+
fi
24+
}
25+
26+
hash_manifest_for_dir() {
27+
local dir="$1"
28+
local manifest_path="$2"
29+
30+
mkdir -p "$(dirname "$manifest_path")"
31+
: > "$manifest_path"
32+
33+
if [ ! -d "$dir" ]; then
34+
return
35+
fi
36+
37+
while IFS= read -r file; do
38+
local rel_path="${file#$dir/}"
39+
local hash
40+
hash="$(shasum "$file" | awk '{print $1}')"
41+
printf "%s\t%s\n" "$rel_path" "$hash" >> "$manifest_path"
42+
done < <(find "$dir" -type f | LC_ALL=C sort)
43+
}
44+
45+
hash_for_path() {
46+
local manifest_path="$1"
47+
local rel_path="$2"
48+
awk -F '\t' -v path="$rel_path" '$1 == path { print $2; found=1; exit } END { if (!found) print "-" }' "$manifest_path"
49+
}
50+
51+
sync_platform_with_conflict_detection() {
52+
local package_name="$1"
53+
local platform_name="$2"
54+
local package_dir="$3"
55+
local shared_dir="$4"
56+
57+
mkdir -p "$STATE_DIR"
58+
mkdir -p "$package_dir" "$shared_dir"
59+
60+
local baseline_manifest="$STATE_DIR/${package_name}_${platform_name}.manifest"
61+
local tmp_baseline_manifest
62+
local tmp_shared_manifest
63+
local tmp_package_manifest
64+
local tmp_union_paths
65+
local tmp_conflicts
66+
67+
tmp_baseline_manifest="$(mktemp)"
68+
tmp_shared_manifest="$(mktemp)"
69+
tmp_package_manifest="$(mktemp)"
70+
tmp_union_paths="$(mktemp)"
71+
tmp_conflicts="$(mktemp)"
72+
73+
if [ -f "$baseline_manifest" ]; then
74+
cp "$baseline_manifest" "$tmp_baseline_manifest"
75+
fi
76+
77+
hash_manifest_for_dir "$shared_dir" "$tmp_shared_manifest"
78+
hash_manifest_for_dir "$package_dir" "$tmp_package_manifest"
79+
80+
cat "$tmp_baseline_manifest" "$tmp_shared_manifest" "$tmp_package_manifest" \
81+
| awk -F '\t' 'NF > 0 { print $1 }' \
82+
| LC_ALL=C sort -u > "$tmp_union_paths"
83+
84+
local shared_changed=0
85+
local package_changed=0
86+
local conflict_count=0
87+
88+
while IFS= read -r rel_path; do
89+
[ -z "$rel_path" ] && continue
90+
91+
local baseline_hash
92+
local shared_hash
93+
local package_hash
94+
baseline_hash="$(hash_for_path "$tmp_baseline_manifest" "$rel_path")"
95+
shared_hash="$(hash_for_path "$tmp_shared_manifest" "$rel_path")"
96+
package_hash="$(hash_for_path "$tmp_package_manifest" "$rel_path")"
97+
98+
if [ "$shared_hash" != "$baseline_hash" ]; then
99+
shared_changed=1
100+
fi
101+
if [ "$package_hash" != "$baseline_hash" ]; then
102+
package_changed=1
103+
fi
104+
105+
if [ "$shared_hash" != "$package_hash" ] && [ "$shared_hash" != "$baseline_hash" ] && [ "$package_hash" != "$baseline_hash" ]; then
106+
conflict_count=$((conflict_count + 1))
107+
printf "%s (shared-native=%s, package=%s, baseline=%s)\n" \
108+
"$rel_path" "$shared_hash" "$package_hash" "$baseline_hash" >> "$tmp_conflicts"
109+
fi
110+
done < "$tmp_union_paths"
111+
112+
if [ "$conflict_count" -gt 0 ]; then
113+
echo "Conflict detected for $package_name [$platform_name]."
114+
echo "Both shared-native and package mirror changed the same file(s) differently since last sync:"
115+
cat "$tmp_conflicts"
116+
rm -f "$tmp_baseline_manifest" "$tmp_shared_manifest" "$tmp_package_manifest" "$tmp_union_paths" "$tmp_conflicts"
117+
return 1
118+
fi
119+
120+
if [ "$package_changed" -eq 1 ] && [ "$shared_changed" -eq 0 ]; then
121+
sync_dir_contents "$package_dir" "$shared_dir"
122+
echo "Applied $platform_name sync direction: package -> shared-native ($package_name)"
123+
elif [ "$shared_changed" -eq 1 ] && [ "$package_changed" -eq 0 ]; then
124+
sync_dir_contents "$shared_dir" "$package_dir"
125+
echo "Applied $platform_name sync direction: shared-native -> package ($package_name)"
126+
fi
127+
128+
hash_manifest_for_dir "$shared_dir" "$baseline_manifest"
129+
rm -f "$tmp_baseline_manifest" "$tmp_shared_manifest" "$tmp_package_manifest" "$tmp_union_paths" "$tmp_conflicts"
130+
}
131+
132+
sync_from_package() {
133+
local package_name="$1"
134+
local android_package_dir="$ROOT_DIR/$package_name/android/src/main/java/com/streamchatreactnative/shared"
135+
local ios_package_dir="$ROOT_DIR/$package_name/ios/shared"
136+
137+
sync_platform_with_conflict_detection \
138+
"$package_name" \
139+
"android" \
140+
"$android_package_dir" \
141+
"$SHARED_ANDROID_DIR"
142+
143+
sync_platform_with_conflict_detection \
144+
"$package_name" \
145+
"ios" \
146+
"$ios_package_dir" \
147+
"$SHARED_IOS_DIR"
148+
}
149+
150+
case "$TARGET" in
151+
native-package)
152+
sync_from_package "native-package"
153+
;;
154+
expo-package)
155+
sync_from_package "expo-package"
156+
;;
157+
all)
158+
# Prefer native-package when both are present.
159+
if [ -d "$ROOT_DIR/native-package/android/src/main/java/com/streamchatreactnative/shared" ] || [ -d "$ROOT_DIR/native-package/ios/shared" ]; then
160+
sync_from_package "native-package"
161+
elif [ -d "$ROOT_DIR/expo-package/android/src/main/java/com/streamchatreactnative/shared" ] || [ -d "$ROOT_DIR/expo-package/ios/shared" ]; then
162+
sync_from_package "expo-package"
163+
else
164+
echo "No package shared native sources found to sync from"
165+
exit 1
166+
fi
167+
;;
168+
*)
169+
echo "Unknown target: $TARGET"
170+
echo "Expected one of: native-package, expo-package, all"
171+
exit 1
172+
;;
173+
esac
174+
175+
echo "Reconciled package/shared-native directories with conflict checks for target: $TARGET"

package/scripts/sync-shimmer-from-package.sh

Lines changed: 0 additions & 75 deletions
This file was deleted.

0 commit comments

Comments
 (0)