Skip to content

Commit 9e49ee2

Browse files
committed
Merge branch 'master' into feat-style-compile-251012
2 parents ef01c4d + 14aa457 commit 9e49ee2

9 files changed

Lines changed: 262 additions & 12 deletions

File tree

analyze_git_stats.py

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import subprocess
2+
import sys
3+
import argparse
4+
from collections import defaultdict
5+
from datetime import datetime
6+
7+
def analyze_git_stats():
8+
# Parse command line arguments
9+
parser = argparse.ArgumentParser(description='Analyze git contribution stats.')
10+
parser.add_argument('--since', type=str, default="1 year ago",
11+
help='Start time period to analyze (e.g. "1 year ago", "2023-01-01")')
12+
parser.add_argument('--until', type=str, default=None,
13+
help='End time period to analyze (e.g. "now", "1 month ago", "2024-01-01"). Defaults to now.')
14+
args = parser.parse_args()
15+
16+
# Configuration
17+
since_date = args.since
18+
until_date = args.until
19+
20+
# Author Alias Mapping
21+
# Format: 'Alias Name': 'Canonical Name'
22+
AUTHOR_MAPPINGS = {
23+
'wangshunnn': 'Soon Wang',
24+
'mackwang112': 'mackwang',
25+
'wangxiaokou': 'wangcuijuan',
26+
'dongxingxingdong': 'WX-DongXing',
27+
'yandadaFreedom': 'lareinayanyu'
28+
# Add more mappings here as needed
29+
}
30+
31+
# Using 'git log' to get the data
32+
# --numstat: shows added/deleted lines
33+
# --no-merges: optional, generally we want to count actual code contributions, not merge commits
34+
# --pretty=format:"AUTHOR:%aN": helps us identify who made the commit
35+
cmd = [
36+
"git", "log",
37+
f"--since={since_date}",
38+
"--numstat",
39+
"--pretty=format:AUTHOR:%aN",
40+
"--no-merges"
41+
]
42+
43+
if until_date:
44+
cmd.append(f"--until={until_date}")
45+
46+
try:
47+
# Run the command with utf-8 encoding errors ignored to prevent crashing on binary filenames or weird author names
48+
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, errors='replace')
49+
stdout, stderr = process.communicate()
50+
51+
if process.returncode != 0:
52+
print(f"Error executing git command: {stderr}")
53+
return
54+
55+
except FileNotFoundError:
56+
print("Error: 'git' command not found. Please ensure git is installed.")
57+
return
58+
59+
# Data structure:
60+
# stats = {
61+
# author: {
62+
# 'total': {'added': 0, 'deleted': 0, 'commits': 0},
63+
# 'lt_1000': {'added': 0, 'deleted': 0, 'commits': 0},
64+
# 'lt_5000': {'added': 0, 'deleted': 0, 'commits': 0}
65+
# }
66+
# }
67+
stats = defaultdict(lambda: {
68+
'total': {'added': 0, 'deleted': 0, 'commits': 0},
69+
'lt_1000': {'added': 0, 'deleted': 0, 'commits': 0},
70+
'lt_5000': {'added': 0, 'deleted': 0, 'commits': 0}
71+
})
72+
73+
lines = stdout.split('\n')
74+
75+
pending_author = None
76+
pending_commit_stats = {'added': 0, 'deleted': 0}
77+
78+
def finalize_commit(author, commit_stats):
79+
if not author:
80+
return
81+
82+
added = commit_stats['added']
83+
deleted = commit_stats['deleted']
84+
total_change = added + deleted
85+
86+
# Add to Total
87+
stats[author]['total']['added'] += added
88+
stats[author]['total']['deleted'] += deleted
89+
stats[author]['total']['commits'] += 1
90+
91+
# Add to < 5000
92+
if total_change < 5000:
93+
stats[author]['lt_5000']['added'] += added
94+
stats[author]['lt_5000']['deleted'] += deleted
95+
stats[author]['lt_5000']['commits'] += 1
96+
97+
# Add to < 1000
98+
if total_change < 1000:
99+
stats[author]['lt_1000']['added'] += added
100+
stats[author]['lt_1000']['deleted'] += deleted
101+
stats[author]['lt_1000']['commits'] += 1
102+
103+
for line in lines:
104+
line = line.strip()
105+
if not line:
106+
continue
107+
108+
if line.startswith("AUTHOR:"):
109+
# Finish previous commit
110+
finalize_commit(pending_author, pending_commit_stats)
111+
112+
# Start new commit
113+
raw_author = line.split("AUTHOR:", 1)[1].strip()
114+
pending_author = AUTHOR_MAPPINGS.get(raw_author, raw_author)
115+
pending_commit_stats = {'added': 0, 'deleted': 0}
116+
else:
117+
# It's a numstat line: "added deleted filepath"
118+
parts = line.split(maxsplit=2)
119+
if len(parts) == 3:
120+
added, deleted, _ = parts
121+
122+
# Handle binary files or other non-numeric entries
123+
if added == '-' or deleted == '-':
124+
continue
125+
126+
try:
127+
pending_commit_stats['added'] += int(added)
128+
pending_commit_stats['deleted'] += int(deleted)
129+
except ValueError:
130+
continue
131+
132+
# Finalize the last commit
133+
finalize_commit(pending_author, pending_commit_stats)
134+
135+
# Output formatting
136+
def print_table(title, key_type):
137+
print(f"\n{title}")
138+
print(f"{'Author':<30} | {'Added':<10} | {'Deleted':<10} | {'Total Lines':<12} | {'Commits':<8}")
139+
print("-" * 80)
140+
141+
# Convert to list for sorting
142+
results = []
143+
for author, data in stats.items():
144+
category_data = data[key_type]
145+
total_changed = category_data['added'] + category_data['deleted']
146+
# Only include if they have commits in this category
147+
if category_data['commits'] > 0:
148+
results.append({
149+
'author': author,
150+
'added': category_data['added'],
151+
'deleted': category_data['deleted'],
152+
'total': total_changed,
153+
'commits': category_data['commits']
154+
})
155+
156+
# Sort by total lines changed (descending)
157+
results.sort(key=lambda x: x['total'], reverse=True)
158+
159+
total_added_all = 0
160+
total_deleted_all = 0
161+
total_commits_all = 0
162+
163+
for r in results:
164+
print(f"{r['author']:<30} | {r['added']:<10} | {r['deleted']:<10} | {r['total']:<12} | {r['commits']:<8}")
165+
total_added_all += r['added']
166+
total_deleted_all += r['deleted']
167+
total_commits_all += r['commits']
168+
169+
print("-" * 80)
170+
print(f"{'TOTAL':<30} | {total_added_all:<10} | {total_deleted_all:<10} | {total_added_all+total_deleted_all:<12} | {total_commits_all:<8}")
171+
172+
print_table("=== ALL COMMITS ===", 'total')
173+
print_table("=== COMMITS < 5000 LINES ===", 'lt_5000')
174+
print_table("=== COMMITS < 1000 LINES ===", 'lt_1000')
175+
176+
if __name__ == "__main__":
177+
analyze_git_stats()

packages/api-proxy/src/platform/api/route/index.ios.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,10 @@ function navigateBack (options = {}) {
104104
}
105105
if (delta >= routeLength && global.__mpx?.config.rnConfig.onAppBack?.(delta - routeLength + 1)) {
106106
nextTick(() => {
107-
navigationHelper.lastSuccessCallback()
108-
navigationHelper.lastSuccessCallback = null
107+
if (navigationHelper.lastSuccessCallback) {
108+
navigationHelper.lastSuccessCallback()
109+
navigationHelper.lastSuccessCallback = null
110+
}
109111
})
110112
} else {
111113
navigation.pop(delta)

packages/webpack-plugin/lib/resolver/AddModePlugin.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,31 @@ module.exports = class AddModePlugin {
3939

4040
const queryObj = parseQuery(request.query || '?')
4141
const queryInfix = queryObj.infix
42-
if (!implicitMode) queryObj.mode = mode
43-
queryObj.infix = `${queryInfix || ''}.${mode}`
4442

4543
// 如果已经确认是mode后缀的文件,添加query与mode后直接返回
4644
if (modePattern.test(path.basename(resourcePath))) {
47-
request.query = stringifyQuery(queryObj)
48-
request.mode = obj.mode
45+
// 已经被resolved到对应mode的文件,避免重复添加mode
46+
const isResolved = (implicitMode || queryObj.mode === mode) && modePattern.test(queryObj.infix)
47+
if (!isResolved) {
48+
queryObj.infix = `${queryInfix || ''}.${mode}`
49+
if (!implicitMode) queryObj.mode = mode
50+
request.query = stringifyQuery(queryObj)
51+
request.mode = obj.mode
52+
}
4953
return callback()
5054
} else if (defaultMode && defaultModePattern.test(path.basename(resourcePath))) {
51-
queryObj.infix = `${queryInfix || ''}.${defaultMode}`
52-
request.query = stringifyQuery(queryObj)
53-
request.mode = obj.mode
55+
const isResolved = (implicitMode || queryObj.mode === mode) && defaultModePattern.test(queryObj.infix)
56+
if (!isResolved) {
57+
queryObj.infix = `${queryInfix || ''}.${defaultMode}`
58+
if (!implicitMode) queryObj.mode = mode
59+
request.query = stringifyQuery(queryObj)
60+
request.mode = obj.mode
61+
}
5462
return callback()
5563
}
5664

65+
if (!implicitMode) queryObj.mode = mode
66+
queryObj.infix = `${queryInfix || ''}.${mode}`
5767
obj.query = stringifyQuery(queryObj)
5868
obj.path = addInfix(resourcePath, mode, extname)
5969
obj.relativePath = request.relativePath && addInfix(request.relativePath, mode, extname)

packages/webpack-plugin/lib/runtime/components/react/mpx-view.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ function backgroundSize (imageProps: ImageProps, preImageInfo: PreImageInfo, ima
287287
} else { // 数值类型 ImageStyle
288288
// 数值类型设置为 stretch
289289
imageProps.resizeMode = 'stretch'
290-
if (type === 'linear' && (!layoutWidth || !layoutHeight)) {
290+
if (type === 'linear' && (!layoutWidth || !layoutHeight) && (isPercent(width) || isPercent(height))) {
291291
// ios 上 linear 组件只要重新触发渲染,在渲染过程中外层容器 width 或者 height 被设置为 0,通过设置 % 的方式会渲染不出来,即使后面再更新为正常宽高也渲染不出来
292292
// 所以 hack 手动先将 linear 宽高也设置为 0,后面再更新为正确的数值或 %。
293293
dimensions = {
@@ -777,7 +777,6 @@ const _View = forwardRef<HandlerRef<View, _ViewProps>, _ViewProps>((viewProps, r
777777
ref: nodeRef,
778778
style: enableStyleAnimation ? [viewStyle, animationStyle] : viewStyle
779779
}
780-
781780
),
782781
[
783782
'hover-start-time',
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<template>
2+
<view> ali </view>
3+
</template>
4+
5+
<script>
6+
import { createComponent } from '@mpxjs/core'
7+
8+
createComponent({})
9+
</script>
10+
11+
<script type="application/json">
12+
{
13+
"component": true
14+
}
15+
</script>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<template>
2+
<view> ali </view>
3+
</template>
4+
5+
<script>
6+
import { createComponent } from '@mpxjs/core'
7+
8+
createComponent({})
9+
</script>
10+
11+
<script type="application/json">
12+
{
13+
"component": true
14+
}
15+
</script>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<template>
2+
<view> ali </view>
3+
</template>
4+
5+
<script>
6+
import { createComponent } from '@mpxjs/core'
7+
8+
createComponent({})
9+
</script>
10+
11+
<script type="application/json">
12+
{
13+
"component": true
14+
}
15+
</script>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<template>
2+
<view> wx </view>
3+
</template>
4+
5+
<script>
6+
import { createComponent } from '@mpxjs/core'
7+
8+
createComponent({})
9+
</script>
10+
11+
<script type="application/json">
12+
{
13+
"component": true
14+
}
15+
</script>

test/e2e/miniprogram-project/src/pages/index.mpx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<view>
33
<list></list>
44
<customOutputComp></customOutputComp>
5+
<mode></mode>
56
</view>
67
</template>
78

@@ -17,7 +18,8 @@
1718
{
1819
"usingComponents": {
1920
"list": "../components/list",
20-
"customOutputComp": "../components/customOutputCom.mpx"
21+
"customOutputComp": "../components/customOutputCom.mpx",
22+
"mode": "../components/mode",
2123
}
2224
}
2325
</script>

0 commit comments

Comments
 (0)